---
title: Workspace
description: Your own folder on a small computer with Python, Node and a shell. 5 tools.
group: workspace
tools: [workspace.bash, workspace.read, workspace.write, workspace.edit, workspace.open]
source: [packages/agents/src/tools/workspace.ts, packages/workspace/src]
generated: true
---

> Roadstar docs for agents. Every page, as markdown: https://docs.roadstar.app/llms.txt

A small computer the owner's agents share, where files stay between runs. Each agent has its own folder. Use it for spreadsheets, Office files, charts and anything that needs code.

- Files come in with `open`: Drive files and email attachments land in `/work/inbox`, Google files as .xlsx, .docx and .pptx.
- Code runs with `bash`, such as `python report.py`. It has no internet.
- Files go out through other tools: `files.save` puts one in Drive, and mail's `attach` takes `{ "workspace": "<path>" }`.
- `/work/shared` is for what you leave another agent.

Code can call your other tools, with the same checks: `from roadstar import mail` in Python. A call the check holds back returns `not_done_yet` or `refused` and the code carries on: ask the owner once the run is done.

Nothing here touches the owner's own things, so these tools need no yes.

## How to use it

What `find_tools` sends with these tools, word for word:

> A small computer the owner's agents share, where files stay between runs: Python 3 with pandas, numpy, openpyxl, XlsxWriter, python-pptx, python-docx, pypdf and matplotlib, Node and a shell, and no internet. Runs start in your own folder; /work/inbox holds files opened from Drive and mail, and /work/shared is for what you leave another agent. Edit Office files here with code. Files leave through your other tools, which take a workspace path: files.save puts one in Drive, and mail's attach takes {workspace: path}. Code calls your other tools as `group.action(...)`, with the same input and checks: in Python, `from roadstar import mail`; in JavaScript, in a script in your folder, `import { mail } from "roadstar"` and await each call. A call the check holds back returns {not_done_yet} or {refused} and the code carries on; ask the owner in your reply once the run is done. A refused call raises ToolError. Write scripts to files and run them, such as `python report.py`, and write results to files from code: the shell can't pipe or redirect node's or python's output. Only a run's output reaches you, cut to 20,000 characters, so print what you need. Formulas are saved, not worked out: Excel and Sheets do that on open. A run stops after 120 s or 300 tool calls.

## Tools

| Tool | What it does | Owner's yes |
| --- | --- | --- |
| [workspace.bash](#bash) | Run a shell command in your folder, such as `python report.py`: its output, exit code and the tools its code called | No |
| [workspace.read](#read) | A text file's lines from offset (1 is the first), 2,000 at a time; nextOffset gives the rest. A binary file, such as .xlsx, gives its size: work on it with code | No |
| [workspace.write](#write) | Write a text file, making its folders; replaces one that's there | No |
| [workspace.edit](#edit) | Replace exact text in a text file; oldText must appear once | No |
| [workspace.open](#open) | Copy Drive files and email attachments into /work/inbox. Google Sheets, Docs and Slides arrive as .xlsx, .docx and .pptx. Each file's path, and from: the Drive file it came from, for files.save's over | No |

## bash

`workspace.bash` · Run a shell command in your folder, such as `python report.py`: its output, exit code and the tools its code called.

**Owner's yes:** No. Nothing of the owner's changes.

| Input | Type | Required | Limits |
| --- | --- | --- | --- |
| `command` | text | yes | 1–20,000 characters |

Returns:

```ts
{
  calls: Record<string, number>;
  tookMs: number;
  usage: RunUsage;
  stopped?: string;
  exitCode: number | null;
  output: string;
}
```

## read

`workspace.read` · A text file's lines from offset (1 is the first), 2,000 at a time; nextOffset gives the rest. A binary file, such as .xlsx, gives its size: work on it with code.

**Owner's yes:** No. Nothing of the owner's changes.

| Input | Type | Required | Limits |
| --- | --- | --- | --- |
| `path` | text | yes | 1–500 characters |
| `offset` | whole number | no | 1 or more |
| `limit` | whole number | no | 1–2000 |

Returns:

```ts
{
  path: string;
  text: string;
  totalLines: number;
  nextOffset: number | null;
} | {
  path: string;
  binary: true;
  size: number;
}
```

## write

`workspace.write` · Write a text file, making its folders; replaces one that's there.

**Owner's yes:** No. Nothing of the owner's changes.

| Input | Type | Required | Limits |
| --- | --- | --- | --- |
| `path` | text | yes | 1–500 characters |
| `content` | text | yes | up to 2,000,000 characters |

Returns:

```ts
{
  path: string;
  size: number;
}
```

## edit

`workspace.edit` · Replace exact text in a text file; oldText must appear once.

**Owner's yes:** No. Nothing of the owner's changes.

| Input | Type | Required | Limits |
| --- | --- | --- | --- |
| `path` | text | yes | 1–500 characters |
| `oldText` | text | yes | 1–200,000 characters |
| `newText` | text | yes | up to 200,000 characters |

Returns:

```ts
{
  path: string;
  size: number;
}
```

## open

`workspace.open` · Copy Drive files and email attachments into /work/inbox. Google Sheets, Docs and Slides arrive as .xlsx, .docx and .pptx. Each file's path, and from: the Drive file it came from, for files.save's over.

**Owner's yes:** No. Nothing of the owner's changes.

| Input | Type | Required | What it is | Limits |
| --- | --- | --- | --- | --- |
| `files` | list of text | no | Drive files: ids from search or the files tools, or links | up to 20 items, each 3–500 characters |
| `attachments` | list of `{ email?, attachment }` | no | An attachment's id from search; for mail not in search, the thread's id from mail search and the id mail read listed | up to 20 items |
| `attachments[].email` | text | no |  | 3–500 characters |
| `attachments[].attachment` | text | yes |  | 3–300 characters |

Returns:

```ts
{
  opened: Record<string, unknown>[];
}
```

## Types

Named types in the results above.

```ts
type RunUsage = {
  cpuMs: number;
  peakBytes: number;
  tookMs: number;
  bytesWritten: number;
}
```
