eve 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/README.md +14 -0
- package/dist/src/cli/banner.d.ts +6 -3
- package/dist/src/cli/banner.js +1 -1
- package/dist/src/cli/commands/init.js +1 -1
- package/dist/src/cli/dev/tui/agent-header.js +1 -1
- package/dist/src/cli/run.js +1 -1
- package/dist/src/evals/runner/run-evals.d.ts +1 -1
- package/dist/src/harness/input-requests.d.ts +20 -1
- package/dist/src/harness/input-requests.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/protocol/message.d.ts +11 -2
- package/dist/src/protocol/message.js +2 -2
- package/dist/src/public/next/index.d.ts +1 -7
- package/dist/src/public/next/index.js +1 -1
- package/dist/src/public/next/vercel-output-config.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/setup/scaffold/create/web-template.d.ts +1 -1
- package/dist/src/setup/scaffold/create/web-template.js +27 -4
- package/dist/src/setup/scaffold/update/channels.js +1 -1
- package/docs/README.md +19 -5
- package/docs/agent-config.md +16 -19
- package/docs/channels/custom.mdx +24 -18
- package/docs/channels/discord.mdx +25 -13
- package/docs/channels/eve.mdx +24 -6
- package/docs/channels/github.mdx +41 -10
- package/docs/channels/linear.mdx +29 -36
- package/docs/channels/overview.mdx +16 -4
- package/docs/channels/slack.mdx +59 -32
- package/docs/channels/teams.mdx +19 -7
- package/docs/channels/telegram.mdx +23 -9
- package/docs/channels/twilio.mdx +28 -6
- package/docs/concepts/context-control.md +24 -41
- package/docs/concepts/default-harness.md +19 -9
- package/docs/concepts/execution-model-and-durability.md +14 -14
- package/docs/concepts/security-model.md +32 -8
- package/docs/concepts/sessions-runs-and-streaming.md +11 -9
- package/docs/connections.mdx +49 -29
- package/docs/evals/assertions.mdx +30 -29
- package/docs/evals/cases.mdx +10 -10
- package/docs/evals/judge.mdx +14 -14
- package/docs/evals/overview.mdx +15 -17
- package/docs/evals/reporters.mdx +19 -7
- package/docs/evals/running.mdx +2 -2
- package/docs/evals/targets.mdx +15 -4
- package/docs/getting-started.mdx +70 -31
- package/docs/guides/auth-and-route-protection.md +18 -12
- package/docs/guides/client/continuations.mdx +5 -13
- package/docs/guides/client/messages.mdx +2 -2
- package/docs/guides/client/output-schema.mdx +2 -2
- package/docs/guides/client/overview.mdx +4 -4
- package/docs/guides/client/streaming.mdx +6 -5
- package/docs/guides/deployment.md +22 -20
- package/docs/guides/dev-tui.md +85 -13
- package/docs/guides/dynamic-capabilities.md +24 -8
- package/docs/guides/dynamic-workflows.md +33 -12
- package/docs/guides/frontend/nextjs.mdx +28 -14
- package/docs/guides/frontend/nuxt.mdx +21 -4
- package/docs/guides/frontend/overview.mdx +11 -11
- package/docs/guides/frontend/sveltekit.mdx +20 -3
- package/docs/guides/frontend/use-eve-agent-svelte.mdx +106 -14
- package/docs/guides/frontend/use-eve-agent-vue.mdx +108 -15
- package/docs/guides/hooks.md +14 -60
- package/docs/guides/instrumentation.md +24 -18
- package/docs/guides/remote-agents.md +19 -15
- package/docs/guides/session-context.md +12 -12
- package/docs/guides/state.md +25 -9
- package/docs/instructions.mdx +18 -10
- package/docs/introduction.md +12 -12
- package/docs/legal.md +16 -0
- package/docs/meta.json +1 -0
- package/docs/reference/cli.md +101 -53
- package/docs/reference/meta.json +1 -1
- package/docs/reference/project-layout.md +39 -32
- package/docs/reference/typescript-api.md +1 -1
- package/docs/sandbox.mdx +25 -19
- package/docs/schedules.mdx +16 -14
- package/docs/skills.mdx +8 -6
- package/docs/subagents.mdx +39 -13
- package/docs/tools.mdx +13 -9
- package/docs/tutorial/connect-a-warehouse.mdx +16 -7
- package/docs/tutorial/first-agent.mdx +21 -11
- package/docs/tutorial/guard-the-spend.mdx +11 -9
- package/docs/tutorial/how-it-runs.mdx +10 -8
- package/docs/tutorial/query-sample-data.mdx +8 -8
- package/docs/tutorial/remember-definitions.mdx +5 -5
- package/docs/tutorial/run-analysis.mdx +13 -11
- package/docs/tutorial/ship-it.mdx +70 -14
- package/docs/tutorial/team-playbooks.mdx +33 -10
- package/package.json +1 -1
|
@@ -9,14 +9,14 @@ Eve builds an agent by walking the filesystem under `agent/`. Each directory is
|
|
|
9
9
|
|
|
10
10
|
Identity comes from the path. You never write a `name` or `id` field on a `define*` call.
|
|
11
11
|
|
|
12
|
-
| Path |
|
|
12
|
+
| Path | Resolves to |
|
|
13
13
|
| ------------------------------------- | --------------------- |
|
|
14
14
|
| `agent/tools/get_weather.ts` | tool `get_weather` |
|
|
15
15
|
| `agent/connections/linear.ts` | connection `linear` |
|
|
16
16
|
| `agent/skills/summarize.md` | skill `summarize` |
|
|
17
17
|
| `agent/subagents/researcher/agent.ts` | subagent `researcher` |
|
|
18
18
|
|
|
19
|
-
The root agent takes its name from the enclosing `package.json` `name`. A subagent takes its name from its directory.
|
|
19
|
+
The root agent takes its name from the enclosing `package.json` `name`, falling back to the app-root directory name when `package.json` has no `name`. A subagent takes its name from its directory.
|
|
20
20
|
|
|
21
21
|
## Recommended layout
|
|
22
22
|
|
|
@@ -24,38 +24,43 @@ The root agent takes its name from the enclosing `package.json` `name`. A subage
|
|
|
24
24
|
my-agent/
|
|
25
25
|
├── package.json
|
|
26
26
|
├── tsconfig.json
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
27
|
+
├── agent/
|
|
28
|
+
│ ├── agent.ts
|
|
29
|
+
│ ├── instructions.md
|
|
30
|
+
│ ├── instrumentation.ts
|
|
31
|
+
│ ├── channels/
|
|
32
|
+
│ ├── connections/
|
|
33
|
+
│ ├── hooks/
|
|
34
|
+
│ ├── skills/
|
|
35
|
+
│ ├── lib/
|
|
36
|
+
│ ├── sandbox/
|
|
37
|
+
│ ├── tools/
|
|
38
|
+
│ ├── schedules/
|
|
39
|
+
│ └── subagents/
|
|
40
|
+
└── evals/
|
|
40
41
|
```
|
|
41
42
|
|
|
43
|
+
Evals live in `evals/` at the app root, a sibling of `agent/`, not inside it. See [Evals](../evals/overview).
|
|
44
|
+
|
|
42
45
|
## Slot table
|
|
43
46
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
|
47
|
-
|
|
|
48
|
-
| `
|
|
49
|
-
| `
|
|
50
|
-
| `
|
|
51
|
-
| `
|
|
52
|
-
| `
|
|
53
|
-
| `
|
|
54
|
-
| `
|
|
55
|
-
| `
|
|
56
|
-
| `
|
|
57
|
-
| `
|
|
58
|
-
| `
|
|
47
|
+
The Subagents column states whether a local subagent (`subagents/<id>/`) can author the slot. A declared subagent inherits nothing from the root; it discovers its own slots. See [Subagents](../subagents).
|
|
48
|
+
|
|
49
|
+
| Path | Description | Subagents | Notes |
|
|
50
|
+
| ------------------------------------------------------- | ------------------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
51
|
+
| `agent.ts` | Runtime config | Yes | Model, modelOptions, compaction, build, experimental. See [Agent config](../agent-config). |
|
|
52
|
+
| `instructions.md` / `instructions.ts` / `instructions/` | Base system prompt | Optional | A flat file, or a directory of `.md` and `.ts` files. Static sources compose at build time. Dynamic sources (`defineDynamic` + `defineInstructions`) resolve at runtime. Required on the root, optional on subagents. |
|
|
53
|
+
| `instrumentation.ts` | Telemetry config | No | OTel exporter and AI SDK span settings, auto-discovered and run before agent code. Root-only. |
|
|
54
|
+
| `channels/` | HTTP / messaging entrypoints | No | Root-only. |
|
|
55
|
+
| `connections/` | External service connections (MCP, OpenAPI) | Yes | One connection per file; name derived from filename. |
|
|
56
|
+
| `hooks/` | Lifecycle and stream-event subscribers | Yes | Module-backed only. Recursive directories supported. |
|
|
57
|
+
| `skills/` | On-demand procedures and capability packs | Yes | Flat markdown, module-backed skills, or packaged skills. Seeded into `/workspace/skills/...`. |
|
|
58
|
+
| `lib/` | Shared authored helper code | Yes | Import-only; not mounted into the workspace. |
|
|
59
|
+
| `sandbox.ts` or `sandbox/sandbox.ts` | The agent's single sandbox | Yes | Use top-level `sandbox.ts` for a definition-only override; use `sandbox/sandbox.ts` + `sandbox/workspace/**` to also seed files. Framework default applies when neither is authored. |
|
|
60
|
+
| `sandbox/workspace/**` | Files seeded into the sandbox | Yes | Mirrored into `/workspace/...` at session bootstrap. |
|
|
61
|
+
| `tools/` | Typed executable integrations | Yes | Module-backed only. |
|
|
62
|
+
| `schedules/` | Recurring jobs | No | Each schedule is `<name>.ts` (default-exported `defineSchedule`) or `<name>.md` (frontmatter `cron:` + prompt body). Recursive nesting supported. Root-only. |
|
|
63
|
+
| `subagents/` | Specialist child agents | Yes | Each child is its own local package under `subagents/<id>/`. Nested subagents are supported. |
|
|
59
64
|
|
|
60
65
|
## What reaches the runtime workspace
|
|
61
66
|
|
|
@@ -74,6 +79,7 @@ A local subagent lives under `subagents/<id>/` and uses the same `agent.ts` shap
|
|
|
74
79
|
agent/subagents/researcher/
|
|
75
80
|
├── agent.ts
|
|
76
81
|
├── instructions.md
|
|
82
|
+
├── connections/
|
|
77
83
|
├── hooks/
|
|
78
84
|
├── skills/
|
|
79
85
|
├── lib/
|
|
@@ -86,7 +92,8 @@ Rules:
|
|
|
86
92
|
|
|
87
93
|
- `agent.ts` is required, and must declare a `description`. The parent reads it on the lowered subagent tool to decide when to delegate.
|
|
88
94
|
- `instructions.md` / `instructions.ts` is optional (unlike the root agent, where it is required).
|
|
89
|
-
- `
|
|
95
|
+
- `connections/`, `hooks/`, `skills/`, `lib/`, `sandbox/`, and `tools/` are all supported, discovered from the subagent's own directory.
|
|
96
|
+
- `channels/` and `schedules/` are not supported inside local subagents.
|
|
90
97
|
- Nested subagents are supported.
|
|
91
98
|
|
|
92
99
|
## Flat layout
|
|
@@ -106,7 +113,7 @@ Prefer the nested layout. It keeps the app root separate from the authored surfa
|
|
|
106
113
|
|
|
107
114
|
## Why didn't Eve discover my file?
|
|
108
115
|
|
|
109
|
-
Run `eve info`. It lists the discovered surface and prints discovery diagnostics. From there, check that the file sits in the right authored slot (per the slot table above) and that the root-vs-subagent boundary is valid. Eve also writes inspectable artifacts under `.eve
|
|
116
|
+
Run `eve info`. It lists the discovered surface and prints discovery diagnostics. From there, check that the file sits in the right authored slot (per the slot table above) and that the root-vs-subagent boundary is valid. Eve also writes inspectable artifacts under `.eve/`. See the debugging artifacts in [instrumentation.ts](../guides/instrumentation) and the [CLI](./cli) reference.
|
|
110
117
|
|
|
111
118
|
## What to read next
|
|
112
119
|
|
|
@@ -54,7 +54,7 @@ A few non-`define*` helpers round out the set: `disableTool` and `ExperimentalWo
|
|
|
54
54
|
|
|
55
55
|
## Runtime context (`ctx`)
|
|
56
56
|
|
|
57
|
-
`ctx` is passed to your tool `execute`, hook handlers, and channel event handlers. It is live only while authored code is
|
|
57
|
+
`ctx` is passed to your tool `execute`, hook handlers, and channel event handlers. It is live only while authored code is running, so reaching for it at module top level throws. See [Session context](../guides/session-context) for the full model.
|
|
58
58
|
|
|
59
59
|
| Member | Use |
|
|
60
60
|
| -------------------------- | ----------------------------------------------------------------------------- |
|
package/docs/sandbox.mdx
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Sandbox"
|
|
3
|
-
description: "The agent's isolated bash environment
|
|
3
|
+
description: "The agent's isolated bash environment, including built-in file tools, a seeded /workspace, backends, lifecycle, and network policy."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
The sandbox is the agent's isolated bash environment: a filesystem rooted at `/workspace` where it can run shell commands, execute scripts, and read or write files without ever touching your app runtime. Every Eve agent has exactly one. The built-in `bash`, `read_file`, `write_file`, `glob`, and `grep` tools already target it, and your authored code can too.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
A working sandbox exists by default, with nothing to author. Override it only to add setup, seed files, pick a backend, or lock down the network.
|
|
9
|
+
|
|
10
|
+
The default sandbox is not a substitute for configuring network policy, credentials, retention, deletion, or other controls your application requires.
|
|
9
11
|
|
|
10
12
|
## Using the sandbox
|
|
11
13
|
|
|
@@ -18,7 +20,7 @@ The model already has shell and file access through the default tools:
|
|
|
18
20
|
| `glob` | find files by pattern |
|
|
19
21
|
| `grep` | search file contents |
|
|
20
22
|
|
|
21
|
-
All of them run with `/workspace` as the working directory. Any authored runtime function (a tool, a step, a model callback) can
|
|
23
|
+
All of them run with `/workspace` as the working directory. Any authored runtime function (a tool, a step, a model callback) can get a live sandbox handle with `ctx.getSandbox()`.
|
|
22
24
|
|
|
23
25
|
```ts title="agent/tools/run_analysis.ts"
|
|
24
26
|
import { defineTool } from "eve/tools";
|
|
@@ -38,7 +40,7 @@ export default defineTool({
|
|
|
38
40
|
|
|
39
41
|
`ctx.getSandbox()` takes no arguments, is async, and only works inside authored runtime execution.
|
|
40
42
|
|
|
41
|
-
`/workspace` is one namespace across every backend, so `/workspace/foo` points at the same file whether the backend is local or Vercel. When you need to interpolate a path into a generated command, `sandbox.resolvePath("repo/build.py")` anchors a relative path to its absolute `/workspace/repo/build.py` form.
|
|
43
|
+
`/workspace` is one namespace across every backend, so `/workspace/foo` points at the same file whether the backend is local or Vercel. When you need to interpolate a path into a generated command, `sandbox.resolvePath("repo/build.py")` anchors a relative path to its absolute `/workspace/repo/build.py` form.
|
|
42
44
|
|
|
43
45
|
The handle does more than `run` and `writeTextFile`. In every method, relative paths resolve from `/workspace` and absolute paths pass through untouched:
|
|
44
46
|
|
|
@@ -53,7 +55,7 @@ The handle does more than `run` and `writeTextFile`. In every method, relative p
|
|
|
53
55
|
| `resolvePath(path)` | anchor a relative path to its absolute `/workspace/...` form |
|
|
54
56
|
| `setNetworkPolicy(policy)` | change egress policy mid-turn (backend-dependent; see [Network policy](#network-policy)) |
|
|
55
57
|
|
|
56
|
-
Since `run` blocks until the command exits,
|
|
58
|
+
Since `run` blocks until the command exits, use `spawn` when the process should keep running while the agent does other work:
|
|
57
59
|
|
|
58
60
|
```ts
|
|
59
61
|
const sandbox = await ctx.getSandbox();
|
|
@@ -66,7 +68,7 @@ A `SandboxProcess` exposes `stdout`/`stderr` byte streams, `wait()` (resolves wi
|
|
|
66
68
|
|
|
67
69
|
`sandbox.id` is a stable per-session identifier that persists across reconnects to the same logical session. Use it as the cache key for per-session state that must outlive individual step executions.
|
|
68
70
|
|
|
69
|
-
The option types (`SandboxSpawnOptions`, `SandboxReadBinaryFileOptions`, `SandboxWriteBinaryFileOptions`, and so on) are named
|
|
71
|
+
The option types (`SandboxSpawnOptions`, `SandboxReadBinaryFileOptions`, `SandboxWriteBinaryFileOptions`, and so on) are named exports from `eve/sandbox`, alongside `SandboxProcess`.
|
|
70
72
|
|
|
71
73
|
## Seeding `/workspace`
|
|
72
74
|
|
|
@@ -80,7 +82,7 @@ agent/sandbox/
|
|
|
80
82
|
scripts/run.sh ← lands at /workspace/scripts/run.sh
|
|
81
83
|
```
|
|
82
84
|
|
|
83
|
-
Every file under `workspace/` mirrors into the sandbox cwd with its structure intact, and Eve lists the top-level entries to the model in the prompt automatically. One subtree is off limits
|
|
85
|
+
Every file under `workspace/` mirrors into the sandbox cwd with its structure intact, and Eve lists the top-level entries to the model in the prompt automatically. One subtree is off limits. Skill discovery already seeds skill files under `/workspace/skills/`, so authoring `agent/sandbox/workspace/skills/...` is rejected; put those under `agent/skills/` instead.
|
|
84
86
|
|
|
85
87
|
## Overriding the sandbox
|
|
86
88
|
|
|
@@ -117,14 +119,14 @@ The backend decides where the sandbox runs. Eve ships four pinned factories from
|
|
|
117
119
|
| `vercel()` | on [Vercel Sandbox](https://vercel.com/docs/sandbox). |
|
|
118
120
|
| `docker()` | locally in a Docker container, driven through the `docker` CLI. |
|
|
119
121
|
| `microsandbox()` | locally in a lightweight [microsandbox](https://www.npmjs.com/package/microsandbox) VM. |
|
|
120
|
-
| `justbash()` | locally in the pure-JS `just-bash` interpreter
|
|
122
|
+
| `justbash()` | locally in the pure-JS `just-bash` interpreter (no daemon or VM, but no real binaries either). |
|
|
121
123
|
| `defaultBackend()` | picks the best available: Vercel Sandbox on hosted Vercel → Docker → microsandbox → just-bash. |
|
|
122
124
|
|
|
123
|
-
Configuring a pinned factory uses that backend unconditionally
|
|
125
|
+
Configuring a pinned factory uses that backend unconditionally. `docker()` always requires a reachable Docker daemon, and `vercel()` always creates hosted sandboxes (including from local dev, with Vercel credentials).
|
|
124
126
|
|
|
125
127
|
With `backend` omitted, Eve uses `defaultBackend()`, which resolves on first use in priority order:
|
|
126
128
|
|
|
127
|
-
1. **Vercel Sandbox** when deploying on Vercel (`process.env.VERCEL` is set)
|
|
129
|
+
1. **Vercel Sandbox** when deploying on Vercel (`process.env.VERCEL` is set), since local container/VM runtimes can't run there.
|
|
128
130
|
2. **Docker** when a daemon is reachable through a Docker-compatible `docker` CLI (Docker Desktop, OrbStack, Colima, Podman via its docker-compatible CLI; override the binary with `EVE_DOCKER_PATH`).
|
|
129
131
|
3. **microsandbox** when the host supports it: macOS on Apple Silicon, or glibc Linux with KVM enabled.
|
|
130
132
|
4. **just-bash** as the dependency-free fallback.
|
|
@@ -145,24 +147,26 @@ export default defineSandbox({
|
|
|
145
147
|
|
|
146
148
|
### Docker
|
|
147
149
|
|
|
148
|
-
`docker()` drives the Docker CLI directly. The default base image is `ghcr.io/vercel/eve:latest`, Eve's published sandbox runtime image
|
|
150
|
+
`docker()` drives the Docker CLI directly. The default base image is `ghcr.io/vercel/eve:latest`, Eve's published sandbox runtime image. Eve creates `/workspace` and verifies Bash during framework setup, before authored bootstrap code runs. Configure it through `docker({ image, env, pullPolicy, networkPolicy })`, and install authored runtime tools in sandbox bootstrap or provide them through a custom image. Templates are committed as local Docker images and reused across sessions when the sandbox source, seed files, `revalidationKey`, and Docker backend options still match. Sessions run as long-lived containers whose filesystems persist `/workspace` changes across turns for the same durable session. `eve dev` prunes stale template images in the background.
|
|
149
151
|
|
|
150
152
|
### microsandbox
|
|
151
153
|
|
|
152
|
-
`microsandbox()` runs each sandbox in a lightweight local VM with snapshot-backed templates, a `vercel-sandbox` user, and a firewall capable of domain-level network policies and credential brokering
|
|
154
|
+
`microsandbox()` runs each sandbox in a lightweight local VM with snapshot-backed templates, a `vercel-sandbox` user, and a firewall capable of domain-level network policies and credential brokering. It is the closest local match to hosted Vercel Sandbox. The default base image is `ghcr.io/vercel/eve:latest`, Eve's published sandbox runtime image. During framework setup, before authored bootstrap code runs, Eve verifies Bash and creates `/workspace` and the sandbox user. Install authored runtime tools in sandbox bootstrap or provide them through a custom image. Supported hosts are macOS on Apple Silicon, or Linux (glibc) with KVM. The `microsandbox` npm package and its VM runtime are not bundled with Eve, so `eve dev` installs both automatically when missing (disable with `setup: { autoInstall: false }`); production processes fail with actionable install errors instead.
|
|
153
155
|
|
|
154
156
|
### just-bash
|
|
155
157
|
|
|
156
|
-
`justbash()` needs no daemon or VM, but commands run in a simulated bash with a virtual filesystem under `.eve/sandbox-cache
|
|
158
|
+
`justbash()` needs no daemon or VM, but commands run in a simulated bash with a virtual filesystem under `.eve/sandbox-cache/`, with no real binaries (`git`, `node`, package managers) and no network isolation. The `just-bash` package is an optional peer dependency, so `eve dev` installs it into your application automatically when missing (disable with `autoInstall: false`); production processes fail with an actionable install error instead.
|
|
157
159
|
|
|
158
|
-
You can write your own backend
|
|
160
|
+
You can also write your own backend. A `SandboxBackend` is an object with a `name`, a `create`, and an optional `prewarm`. See the `SandboxBackend*` types on `eve/sandbox`.
|
|
159
161
|
|
|
160
162
|
## Lifecycle
|
|
161
163
|
|
|
162
164
|
There are two hooks, scoped differently:
|
|
163
165
|
|
|
164
|
-
- **`bootstrap({ use })`** is template-scoped and runs once when the template is built. Put reusable setup here
|
|
165
|
-
- **`onSession({ use, ctx })`** is durable-session-scoped and runs once per session.
|
|
166
|
+
- **`bootstrap({ use })`** is template-scoped and runs once when the template is built. Put reusable setup here that every later session inherits, such as cloning a baseline repo, installing dependencies, or seeding files. Call `use()` to get a `SandboxSession`. Only template filesystem state and supported backend metadata carry into later sessions; config like network policy does not. If external inputs affect what bootstrap produces, set `revalidationKey: () => string` so Eve knows when to rebuild the template (authored sandbox source and seed contents are already tracked for you).
|
|
167
|
+
- **`onSession({ use, ctx })`** is durable-session-scoped and runs once per session. Put per-session setup here, including network policy, resources, timeout, per-user credentials, and one-time markers. Because it runs inside the active runtime context, it can read `ctx.session` and derive the current principal without baking credentials into the template. Call `use(opts?)` to get a `SandboxSession`; `opts` flow to the backend's update path after create.
|
|
168
|
+
|
|
169
|
+
If you require a network policy or other configuration for every session, configure it on the backend factory or in `onSession`; do not rely on bootstrap-only configuration.
|
|
166
170
|
|
|
167
171
|
```ts
|
|
168
172
|
import { defineSandbox } from "eve/sandbox";
|
|
@@ -179,7 +183,7 @@ export default defineSandbox({
|
|
|
179
183
|
});
|
|
180
184
|
```
|
|
181
185
|
|
|
182
|
-
Sessions are persistent.
|
|
186
|
+
Sessions are persistent, and how the underlying runtime idles out depends on the backend. On the Vercel backend, the VM times out after a period of inactivity (default 30 minutes); Eve preserves the filesystem and resumes the sandbox on the next message as if nothing happened, even days later. The Docker backend keeps a long-lived container per durable session and persists `/workspace` across turns without that timeout, and the just-bash backend stores its virtual filesystem under `.eve/sandbox-cache/`. In every case, `/workspace` survives between turns for the same session.
|
|
183
187
|
|
|
184
188
|
## Network policy
|
|
185
189
|
|
|
@@ -195,7 +199,9 @@ networkPolicy: {
|
|
|
195
199
|
};
|
|
196
200
|
```
|
|
197
201
|
|
|
198
|
-
|
|
202
|
+
Default egress is `allow-all`. For non-public, sensitive, regulated, or production workloads, configure `deny-all` or an explicit allow-list before running untrusted tools or handling sensitive data.
|
|
203
|
+
|
|
204
|
+
Set it on the factory (`vercel({ networkPolicy: "deny-all" })`) and it applies before authored `bootstrap` code runs; framework-owned base setup may briefly keep egress open to install required packages. Set it in `onSession`'s `use()` to override per-session. The common pattern combines both: leave the factory open so `bootstrap` can `git clone`, then lock down in `onSession`. To change the policy mid-turn, call `sandbox.setNetworkPolicy(...)` on the live handle.
|
|
199
205
|
|
|
200
206
|
Domain-level allow-lists and credential brokering are supported by `vercel()` and `microsandbox()`. The Docker backend honors only `"allow-all"` and `"deny-all"` (at creation and via `setNetworkPolicy`); the just-bash backend rejects `setNetworkPolicy` entirely.
|
|
201
207
|
|
|
@@ -208,7 +214,7 @@ async onSession({ use }) {
|
|
|
208
214
|
await use({
|
|
209
215
|
networkPolicy: {
|
|
210
216
|
allow: {
|
|
211
|
-
"github.com": [{ transform: [{ headers: { authorization: "Basic
|
|
217
|
+
"github.com": [{ transform: [{ headers: { authorization: "Basic your_base64_credentials_here" } }] }],
|
|
212
218
|
"*": [],
|
|
213
219
|
},
|
|
214
220
|
},
|
package/docs/schedules.mdx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Schedules"
|
|
3
|
-
description: "Run an agent on a cron cadence
|
|
3
|
+
description: "Run an agent on a cron cadence, either a fire-and-forget prompt or a handler that hands work off to a channel."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
A schedule
|
|
6
|
+
A schedule starts the agent on its own clock instead of waiting for an inbound message. Use one for daily digests, data syncs, cleanup sweeps, heartbeats, or anything that should fire on a cadence. Each one is a single file under `agent/schedules/` carrying a cron expression. Schedules are root-only, so declared subagents cannot have a `schedules/` directory.
|
|
7
7
|
|
|
8
8
|
The name comes from the path under `schedules/` (`agent/schedules/billing/sweep.ts` → `"billing/sweep"`), and nested directories are fine.
|
|
9
9
|
|
|
@@ -25,11 +25,13 @@ interface ScheduleHandlerArgs {
|
|
|
25
25
|
}
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
`defineSchedule` is
|
|
28
|
+
`defineSchedule` is a type-level pass-through. The compiler is what enforces the one-of rule.
|
|
29
|
+
|
|
30
|
+
`cron` is a standard 5-field string (`minute hour day-of-month month day-of-week`) with minute granularity. On Vercel, each schedule becomes a Vercel Cron Job, and Vercel evaluates the expression in UTC, so `"0 9 * * 1-5"` fires at 09:00 UTC on weekdays. `eve dev` never fires schedules on their cron cadence. To trigger one while iterating, use the dispatch route below.
|
|
29
31
|
|
|
30
32
|
## Markdown form (fire-and-forget)
|
|
31
33
|
|
|
32
|
-
This is the minimal schedule. Eve runs the agent on the prompt and throws away the output, though the agent can still call tools, write to backends, and log along the way. We call this task mode. A task-mode session runs to completion or fails
|
|
34
|
+
This is the minimal schedule. Eve runs the agent on the prompt and throws away the output, though the agent can still call tools, write to backends, and log along the way. We call this task mode. A task-mode session runs to completion or fails, and cannot park to wait for a person or an OAuth sign-in.
|
|
33
35
|
|
|
34
36
|
```ts title="agent/schedules/heartbeat.ts"
|
|
35
37
|
import { defineSchedule } from "eve/schedules";
|
|
@@ -54,7 +56,7 @@ Sweep stale workflow state.
|
|
|
54
56
|
|
|
55
57
|
## Handler form (`run`)
|
|
56
58
|
|
|
57
|
-
|
|
59
|
+
Use a handler when the schedule needs to deliver to a channel, branch on conditions, or compute its arguments at fire time. The handler is in full control. It has no channel of its own, so it passes the work to one with `receive`.
|
|
58
60
|
|
|
59
61
|
```ts title="agent/schedules/daily-digest.ts"
|
|
60
62
|
import { defineSchedule } from "eve/schedules";
|
|
@@ -75,30 +77,30 @@ export default defineSchedule({
|
|
|
75
77
|
});
|
|
76
78
|
```
|
|
77
79
|
|
|
78
|
-
- `receive(channel, { message, target, auth })`: starts a session on another channel. Same contract as a route handler
|
|
79
|
-
- `waitUntil(promise)`: extends the cron task
|
|
80
|
+
- `receive(channel, { message, target, auth })`: starts a session on another channel. Same contract as a route handler's `args.receive`.
|
|
81
|
+
- `waitUntil(promise)`: extends the cron task's lifetime so the parked session and any in-flight fetches settle before the task ends. Wrap the `receive` call in it.
|
|
80
82
|
- `appAuth`: the app principal (`{ authenticator: "app", principalId: "eve:app", principalType: "runtime" }`). Pass it as `receive(..., { auth: appAuth })` for work the agent does on its own behalf.
|
|
81
83
|
|
|
82
|
-
A handler-form session runs on the same durable runtime engine as any other session, so it can park, for instance when the channel handoff is waiting for a Slack reply. Only markdown task mode is barred from waiting.
|
|
84
|
+
A handler-form session runs on the same durable runtime engine as any other session, so it can park (durably suspend), for instance when the channel handoff is waiting for a Slack reply. Only markdown task mode is barred from waiting.
|
|
83
85
|
|
|
84
86
|
## Trigger a schedule while iterating
|
|
85
87
|
|
|
86
|
-
|
|
88
|
+
The dev server mounts a one-shot dispatch route that fires a schedule by name, out of band, exactly once. Since `eve dev` never runs schedules on their cron cadence, this is how you trigger one without waiting for the next production tick.
|
|
87
89
|
|
|
88
90
|
```sh
|
|
89
|
-
curl -X POST http://localhost:
|
|
91
|
+
curl -X POST http://localhost:3000/eve/v1/dev/schedules/heartbeat
|
|
90
92
|
# -> { "scheduleId": "heartbeat", "sessionIds": ["..."] }
|
|
91
93
|
```
|
|
92
94
|
|
|
93
|
-
`:scheduleId` is the path-derived schedule name (`agent/schedules/heartbeat.ts` → `heartbeat`; URL-encode the `/` in nested names). It runs the exact dispatch path the production cron handler uses and returns the started session ids as JSON, so you can subscribe to each one
|
|
95
|
+
`:scheduleId` is the path-derived schedule name (`agent/schedules/heartbeat.ts` → `heartbeat`; URL-encode the `/` in nested names). It runs the exact dispatch path the production cron handler uses and returns the started session ids as JSON, so you can subscribe to each one's [stream](./concepts/sessions-runs-and-streaming) at `GET /eve/v1/session/:sessionId/stream`. An unknown id comes back `404` with `availableScheduleIds`, listing the schedules the app actually defines.
|
|
94
96
|
|
|
95
97
|
The route is dev-only. Production builds never mount it, and it needs no auth since the dev server is local-only.
|
|
96
98
|
|
|
97
99
|
## On Vercel
|
|
98
100
|
|
|
99
|
-
Hosted Vercel builds turn every `defineSchedule(...)` into a Vercel Cron Job, with each `cron` written as an entry in `.vercel/output/config.json`. Confirm discovery under Settings → Cron Jobs and watch execution history under Observability → Cron Jobs
|
|
101
|
+
Hosted Vercel builds turn every `defineSchedule(...)` into a Vercel Cron Job, with each `cron` written as an entry in `.vercel/output/config.json`. Vercel evaluates these expressions in UTC. Confirm discovery under **Settings → Cron Jobs** and watch execution history under **Observability → Cron Jobs**. Per-run logs land under **Observability → Logs**.
|
|
100
102
|
|
|
101
103
|
## What to read next
|
|
102
104
|
|
|
103
|
-
-
|
|
104
|
-
-
|
|
105
|
+
- [Channels](./channels/overview): deliver schedule output to users.
|
|
106
|
+
- [Sessions, runs & streaming](./concepts/sessions-runs-and-streaming): inspect a schedule run.
|
package/docs/skills.mdx
CHANGED
|
@@ -3,7 +3,7 @@ title: "Skills"
|
|
|
3
3
|
description: "Author load-on-demand procedures the model pulls into context with load_skill."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
A skill is a model-loadable procedure that follows the `SKILL.md` convention
|
|
6
|
+
A skill is a model-loadable procedure that follows the `SKILL.md` convention. It is a markdown document, optionally a packaged directory with supporting files, that the model pulls into context on demand rather than carrying on every turn. Eve advertises each skill's description, and the model loads the full body only when a turn calls for it. This is progressive disclosure, the same model the broader Agent Skills standard uses, so a skill authored against that standard ports over as-is.
|
|
7
7
|
|
|
8
8
|
## How loading works
|
|
9
9
|
|
|
@@ -25,11 +25,11 @@ The smallest skill is a flat markdown file. The content is the procedure, and th
|
|
|
25
25
|
Use the weather tool before answering forecast or temperature questions.
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
A
|
|
28
|
+
A flat markdown skill can skip the `description` frontmatter. When it does, Eve advertises the first non-empty, non-code-fence line of the body with any leading `#`, `>`, `*`, or `-` marker stripped. If the body has no such line, Eve falls back to the literal `Instructions for the <name> skill.`, which is a weak routing hint, so add a `description` when you want the model to route on intent.
|
|
29
29
|
|
|
30
|
-
`
|
|
30
|
+
A packaged skill is a directory with a `SKILL.md` plus sibling files like `references/`, `assets/`, and `scripts/`. The packaged `SKILL.md` must carry `description` frontmatter; it has no filename slug to fall back on.
|
|
31
31
|
|
|
32
|
-
```md
|
|
32
|
+
```md title="agent/skills/research/SKILL.md"
|
|
33
33
|
---
|
|
34
34
|
description: Research unfamiliar topics before answering with confidence.
|
|
35
35
|
---
|
|
@@ -55,7 +55,9 @@ export default defineSkill({
|
|
|
55
55
|
|
|
56
56
|
Eve generates `SKILL.md` from `markdown`, and each `files` entry becomes a package-relative sibling. Start with plain markdown and move to `defineSkill` only when you hit its limits.
|
|
57
57
|
|
|
58
|
-
Skills are scoped
|
|
58
|
+
## Skills are scoped per agent
|
|
59
|
+
|
|
60
|
+
Skills are scoped to the agent that declares them. A [subagent](./subagents)'s `skills/` are invisible to the root agent, and the reverse holds too. There's no shared-skill mechanism, so put shared executable helpers in `lib/`.
|
|
59
61
|
|
|
60
62
|
## Read skill files at runtime
|
|
61
63
|
|
|
@@ -70,7 +72,7 @@ The handle exposes the skill's `name` and `file(relativePath)`; file content is
|
|
|
70
72
|
|
|
71
73
|
## Dynamic skills
|
|
72
74
|
|
|
73
|
-
|
|
75
|
+
To serve a different skill per principal, tenant, or channel (the caller's own team playbook, say), wrap `defineSkill` in a `defineDynamic` resolver keyed on `ctx.session.auth`. See [Dynamic capabilities](./guides/dynamic-capabilities).
|
|
74
76
|
|
|
75
77
|
## What to read next
|
|
76
78
|
|
package/docs/subagents.mdx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Subagents"
|
|
3
|
-
description: "Delegate work to child agents
|
|
3
|
+
description: "Delegate work to child agents, either a copy of the agent itself or declared specialists with their own sandbox and skills."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
A subagent is a child agent that one agent delegates a focused subtask to. Split work
|
|
6
|
+
A subagent is a child agent that one agent delegates a focused subtask to. Split work into one to run it in parallel, to give the child a narrower set of tools, or to give a specialist its own identity. There are two kinds, the built-in `agent` tool (a copy of the agent itself) and declared subagents (specialists with their own directory).
|
|
7
7
|
|
|
8
8
|
## The built-in `agent` tool
|
|
9
9
|
|
|
@@ -16,7 +16,9 @@ Every agent gets an `agent` tool by default. The model calls it to delegate a su
|
|
|
16
16
|
}
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
The copy shares the parent's sandbox and tools
|
|
19
|
+
The copy shares the parent's sandbox and tools, and a child's file writes are immediately visible to the parent. That is what makes parallel calls natural: fan out a few copies to fix different files at once. The copy inherits auth and connections, but starts with fresh conversation history and fresh state. If a declared subagent calls `agent`, the child is a copy of _that_ subagent, not the root.
|
|
20
|
+
|
|
21
|
+
The parent transfers data to the child through the `message` input it gives the subagent. Do not include sensitive data in a subagent request unless that child and its inherited tools, connections, sandbox, and telemetry path are appropriate for that data.
|
|
20
22
|
|
|
21
23
|
An authored tool at `agent/tools/agent.ts` takes priority over the built-in.
|
|
22
24
|
|
|
@@ -47,30 +49,54 @@ agent/subagents/researcher/
|
|
|
47
49
|
└── subagents/ # optional, nested subagents
|
|
48
50
|
```
|
|
49
51
|
|
|
50
|
-
`schedules/` is not supported inside a declared subagent
|
|
52
|
+
`schedules/` is not supported inside a declared subagent. Schedules are root-only.
|
|
51
53
|
|
|
52
54
|
## The isolation boundary
|
|
53
55
|
|
|
54
|
-
A declared subagent
|
|
56
|
+
A declared subagent inherits nothing from the root's authored slots. Discovery treats its directory as its own agent root, so it has only the instructions, tools, connections, skills, sandbox, hooks, and nested subagents authored under `agent/subagents/<id>/`. An absent slot falls back to the framework default, not to the root's version.
|
|
57
|
+
|
|
58
|
+
| Slot | Built-in `agent` tool | Declared subagent |
|
|
59
|
+
| ------------ | ----------------------------- | -------------------------------------- |
|
|
60
|
+
| Instructions | Inherited (copy of the agent) | Own `instructions.{md,ts}`, optional |
|
|
61
|
+
| Tools | Inherited | Own `tools/` |
|
|
62
|
+
| Connections | Inherited | Own `connections/` |
|
|
63
|
+
| Skills | Inherited | Own `skills/` |
|
|
64
|
+
| Sandbox | Shared with parent | Own `sandbox/`, else framework default |
|
|
65
|
+
| Hooks | Inherited | Own `hooks/` |
|
|
66
|
+
| State | Fresh | Fresh |
|
|
67
|
+
| Channels | Root-only | Root-only |
|
|
68
|
+
| Schedules | Root-only | Root-only |
|
|
55
69
|
|
|
56
|
-
|
|
57
|
-
- The child's sandbox does not inherit from the parent. It falls back to the framework default unless it authors `subagents/<id>/sandbox.ts`, or seeds files via `subagents/<id>/sandbox/workspace/`.
|
|
70
|
+
For a declared subagent this means duplicating anything the child needs. When two subagents need the same procedure, copy the markdown under each `skills/` directory, or share typed helpers via `lib/`. The sandbox does not inherit from the parent; it falls back to the framework default unless the subagent authors `subagents/<id>/sandbox.ts` or seeds files via `subagents/<id>/sandbox/workspace/`.
|
|
58
71
|
|
|
59
|
-
The built-in `agent` tool is the exception
|
|
72
|
+
The built-in `agent` tool is the exception. Its children share the parent's sandbox and tools because they are copies of the same agent working on the same files.
|
|
60
73
|
|
|
61
|
-
`defineState` is never shared, for either kind
|
|
74
|
+
`defineState` is never shared, for either kind. Each child starts with fresh durable state.
|
|
62
75
|
|
|
63
76
|
## What the parent sees
|
|
64
77
|
|
|
65
|
-
Eve lowers every subagent (built-in copy, declared, or [remote](./guides/remote-agents)) into a model-visible tool with the same `{ message, outputSchema? }` shape. The parent packs `message` with everything the child needs, since the child never sees the parent's history. Set `outputSchema`
|
|
78
|
+
Eve lowers every subagent (built-in copy, declared, or [remote](./guides/remote-agents)) into a model-visible tool with the same `{ message, outputSchema? }` shape. The parent packs `message` with everything the child needs, since the child never sees the parent's history. Set `outputSchema` to run the child in task mode, returning structured output as the tool result.
|
|
79
|
+
|
|
80
|
+
A declared subagent's tool name is the bare path-derived name, with no prefix. `agent/subagents/researcher/` registers as the tool `researcher`. Unlike connection tools (`connection__<connection>__<tool>`), it carries no namespace, so the model, approvals, logs, and evals all reference it by that name. Its input schema is:
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
{
|
|
84
|
+
message: string; // all context the child needs; it never sees the parent's history
|
|
85
|
+
outputSchema?: object; // when set, the child runs in task mode and returns structured output
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Because the name lives in the same runtime tool namespace as authored tools, a subagent named `researcher` collides with a tool named `researcher`. Eve rejects the build rather than picking a winner, so keep subagent directory names distinct from tool names.
|
|
90
|
+
|
|
91
|
+
Do not rely on subagent delegation by itself as an approval boundary. Put sensitive tools behind `needsApproval`, connection approval, route/session authorization, or other controls wherever those tools can be called.
|
|
66
92
|
|
|
67
93
|
Each delegated subagent spins up its own child session and stream. The parent stream carries only the control-plane events `subagent.called` and `subagent.completed`. To follow the child's full progress, read `subagent.called.data.childSessionId` and subscribe at `GET /eve/v1/session/:childSessionId/stream`.
|
|
68
94
|
|
|
69
95
|
## When to split
|
|
70
96
|
|
|
71
|
-
Split out a subagent when the task needs a different prompt or specialist role, a narrower tool surface, or its own runtime context. Don't reach for one when a [skill](./skills) would do
|
|
97
|
+
Split out a subagent when the task needs a different prompt or specialist role, a narrower tool surface, or its own runtime context. Don't reach for one when a [skill](./skills) would do. If the agent can keep its identity and needs only an optional procedure, a skill is the lighter choice.
|
|
72
98
|
|
|
73
99
|
## What to read next
|
|
74
100
|
|
|
75
|
-
-
|
|
76
|
-
-
|
|
101
|
+
- [Remote agents](./guides/remote-agents): call another Eve deployment as a subagent.
|
|
102
|
+
- [Dynamic workflows](./guides/dynamic-workflows): have the model orchestrate its subagents programmatically (fan-out, map-reduce).
|
package/docs/tools.mdx
CHANGED
|
@@ -3,7 +3,7 @@ title: "Tools"
|
|
|
3
3
|
description: "Define typed actions the agent can call, and gate sensitive ones on human approval."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
A tool is a typed action the agent can call
|
|
6
|
+
A tool is a typed action the agent can call, such as hitting an API, running a query, or writing a file. The action stays in code you control. Tools run in your app runtime with full access to `process.env`, not in the [sandbox](./sandbox).
|
|
7
7
|
|
|
8
8
|
## Define a tool
|
|
9
9
|
|
|
@@ -33,7 +33,7 @@ When a tool returns structured data, add an optional `outputSchema`. With Zod or
|
|
|
33
33
|
|
|
34
34
|
### The `ctx` parameter
|
|
35
35
|
|
|
36
|
-
`execute` gets a `ctx` carrying the runtime accessors
|
|
36
|
+
`execute` gets a `ctx` carrying the runtime accessors:
|
|
37
37
|
|
|
38
38
|
- `ctx.session`: session metadata, turn, auth, parent lineage.
|
|
39
39
|
- `ctx.getSandbox()`: the live [sandbox](./sandbox) handle.
|
|
@@ -41,13 +41,13 @@ When a tool returns structured data, add an optional `outputSchema`. With Zod or
|
|
|
41
41
|
|
|
42
42
|
Running in the app runtime is what lets a tool import shared code from `lib/`, read `process.env`, and take part in Eve’s durable pause/resume model.
|
|
43
43
|
|
|
44
|
-
Eve never runs authored tools during discovery
|
|
44
|
+
Eve never runs authored tools during discovery. The model sees descriptors first, and only what it actually calls gets executed. Completed steps never re-run; Eve replays the recorded result. A step interrupted mid-execution re-runs, so make non-idempotent side effects like charges or emails idempotent, or gate them with approval.
|
|
45
45
|
|
|
46
46
|
## Human-in-the-loop
|
|
47
47
|
|
|
48
|
-
HITL is
|
|
48
|
+
Human-in-the-loop (HITL) approval is a property of a tool that pauses for a person before (or instead of) running. Gate a tool on approval with `needsApproval` and the helpers from `eve/tools/approval`:
|
|
49
49
|
|
|
50
|
-
```ts
|
|
50
|
+
```ts title="agent/tools/refund_charge.ts"
|
|
51
51
|
import { defineTool } from "eve/tools";
|
|
52
52
|
import { always } from "eve/tools/approval";
|
|
53
53
|
import { z } from "zod";
|
|
@@ -68,13 +68,15 @@ export default defineTool({
|
|
|
68
68
|
| `once()` | Require approval only the first time the tool runs in a session; auto-allow after. |
|
|
69
69
|
| `always()` | Require approval before every call. |
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
By default, omitted `needsApproval` behaves like `never()`, so tool calls may execute without human approval. Require human approval or other safeguards for sensitive, irreversible, regulated, financial, healthcare, employment, housing, legal, safety-impacting, user-impacting, or external side-effecting actions.
|
|
72
|
+
|
|
73
|
+
When the decision depends on the input, pass your own predicate instead of a helper. It receives `{ toolName, toolInput, approvedTools }` and returns a boolean. `toolInput` can be undefined, so guard the access. To require approval only when an amount crosses a threshold:
|
|
72
74
|
|
|
73
75
|
```ts
|
|
74
|
-
needsApproval: ({ toolInput }) => toolInput
|
|
76
|
+
needsApproval: ({ toolInput }) => (toolInput?.amount ?? 0) > 1000,
|
|
75
77
|
```
|
|
76
78
|
|
|
77
|
-
###
|
|
79
|
+
### How approval pause and resume works
|
|
78
80
|
|
|
79
81
|
Approvals and questions share one protocol:
|
|
80
82
|
|
|
@@ -97,7 +99,9 @@ toModelOutput(output) {
|
|
|
97
99
|
},
|
|
98
100
|
```
|
|
99
101
|
|
|
100
|
-
|
|
102
|
+
`toModelOutput` receives the full, typed `execute` return and only affects the model. Channel event handlers and hooks still get the full output on `action.result`, so a channel can render rich platform output (Slack Block Kit, say) the model never sees. Return `{ type: "text", value }` for a summary, or `{ type: "json", value }` for a smaller object.
|
|
103
|
+
|
|
104
|
+
Do not return secrets, credentials, unnecessary personal data, or unbounded sensitive content from tools. Filter, minimize, and redact tool outputs before returning them.
|
|
101
105
|
|
|
102
106
|
## What to read next
|
|
103
107
|
|