diff --git a/.changeset/filesystem-access-flag-undocumented.md b/.changeset/filesystem-access-flag-undocumented.md
new file mode 100644
index 0000000..c9a27ef
--- /dev/null
+++ b/.changeset/filesystem-access-flag-undocumented.md
@@ -0,0 +1,5 @@
+---
+"@generata/core": patch
+---
+
+docs: document filesystemAccess agent option
diff --git a/packages/core/README.md b/packages/core/README.md
index e4fae04..56d5245 100644
--- a/packages/core/README.md
+++ b/packages/core/README.md
@@ -29,33 +29,29 @@ defineWorkflow({
});
```
-## Prompt context
+## Agent options
-Every LLM-backed agent (`worker`, `critic`, `planner`, `dispatcher`) accepts a `promptContext` array on its `defineAgent` options. Each entry names a file to inject into the agent's prompt as an `...` XML block, prepended before the task body. The engine - not the agent author - owns the framing, so templates never need to say "you have X above".
+### `filesystemAccess`
+
+Optional `boolean`. `full`-permission agents (`worker`, `planner`) implicitly receive `Read`, `Glob`, and `Grep` as baseline tools so they can inspect the workspace before writing. Set `filesystemAccess: false` to omit that baseline - useful for write-or-exec-only agents that should not be allowed to read arbitrary files. Omitting the field keeps the baseline (the default).
+
+The flag is a no-op on `read-only` agents (filesystem read is the defining characteristic of that permission level); setting it to `false` on a read-only agent is a parse error.
```ts
-defineAgent({
+import { defineAgent } from "@generata/core";
+
+export default defineAgent({
+ name: "shell-runner",
type: "worker",
- description: "...",
- modelTier: "standard",
- promptContext: [
- { filepath: "NOTES.md" }, // required, full file
- { filepath: "CHANGELOG.md", head: 40 }, // first 40 lines only
- { filepath: "logs/run.log", tail: 200 }, // last 200 lines only
- { filepath: "memory/progress.txt", optional: true }, // skipped if missing
- { filepath: ({ slug }) => `projects/${slug}/SPEC.md` }, // resolved per-call
- ],
- prompt: `...`,
+ permissions: "full",
+ filesystemAccess: false,
+ modelTier: "light",
+ description: "Runs a single shell command without reading source.",
+ tools: ["bash"],
+ prompt: ({ command }) => `Run: ${command}`,
});
```
-| Field | Type | Behaviour |
-| :--------- | :-------------------------------------------- | :------------------------------------------------------------------------ |
-| `filepath` | `string \| (vars: ContextVars) => string` | Resolved relative to the run's working directory. Function form receives the same strict variables as `prompt`, so it can interpolate workflow inputs / step outputs. |
-| `head` | `number` (optional) | Keep only the first N lines of the file. |
-| `tail` | `number` (optional) | Keep only the last N lines. Combine with `head` to take a head-then-tail slice. |
-| `optional` | `boolean` (optional) | If `true` and the file is missing, the entry is skipped silently - no tag, no warning. If `false` (default) and the file is missing, the engine renders `` and prints a `[context] : '' not found` warning to stderr. Use `optional: true` for files that are expected to be absent on fresh systems (e.g. `memory/progress.txt`). |
-
## Running workflows from code
`@generata/core` exposes `runWorkflow` and `runAgent` so you can drive any workflow or agent from your own TypeScript without going through the CLI. This is the primitive for loops, batch jobs, or wrapping generata in a larger script.