eve 0.19.0 → 0.21.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.
Files changed (206) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/src/channel/types.d.ts +9 -5
  3. package/dist/src/chunks/{use-eve-agent-Dvy_Wjvq.js → use-eve-agent-CM24ZUEI.js} +48 -34
  4. package/dist/src/chunks/{use-eve-agent-Bh1NmXO9.js → use-eve-agent-CxcKypLZ.js} +48 -34
  5. package/dist/src/cli/dev/tui/setup-selection-input.js +1 -1
  6. package/dist/src/cli/dev/tui/stream-format.d.ts +4 -0
  7. package/dist/src/cli/dev/tui/stream-format.js +1 -1
  8. package/dist/src/cli/dev/tui/terminal-renderer.js +1 -1
  9. package/dist/src/cli/dev/tui/test/mock-terminal.d.ts +2 -0
  10. package/dist/src/cli/dev/tui/test/mock-terminal.js +1 -1
  11. package/dist/src/client/index.d.ts +1 -1
  12. package/dist/src/client/message-reducer-types.d.ts +11 -3
  13. package/dist/src/client/message-reducer.js +1 -1
  14. package/dist/src/compiler/manifest.js +1 -1
  15. package/dist/src/compiler/normalize-agent-config.js +1 -1
  16. package/dist/src/compiler/workspace-resources.js +1 -1
  17. package/dist/src/context/build-base-tool-context.d.ts +9 -0
  18. package/dist/src/context/build-base-tool-context.js +1 -0
  19. package/dist/src/context/build-dynamic-tools.js +1 -1
  20. package/dist/src/context/dynamic-skill-lifecycle.js +1 -1
  21. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  22. package/dist/src/context/keys.d.ts +0 -1
  23. package/dist/src/context/keys.js +1 -1
  24. package/dist/src/discover/sandbox.d.ts +0 -6
  25. package/dist/src/discover/sandbox.js +1 -1
  26. package/dist/src/evals/cli/eval.js +4 -1
  27. package/dist/src/evals/runner/discover.d.ts +10 -0
  28. package/dist/src/evals/runner/discover.js +1 -1
  29. package/dist/src/execution/create-session-step.d.ts +2 -1
  30. package/dist/src/execution/create-session-step.js +1 -1
  31. package/dist/src/execution/delegated-parent-notification.d.ts +6 -0
  32. package/dist/src/execution/delegated-parent-notification.js +1 -1
  33. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  34. package/dist/src/execution/dispatch-workflow-runtime-actions-step.js +1 -1
  35. package/dist/src/execution/durable-session-migrations/turn-workflow.d.ts +2 -0
  36. package/dist/src/execution/durable-session-store.d.ts +1 -0
  37. package/dist/src/execution/next-driver-action.d.ts +3 -0
  38. package/dist/src/execution/node-step.d.ts +8 -0
  39. package/dist/src/execution/node-step.js +1 -1
  40. package/dist/src/execution/run-session-limits.d.ts +21 -0
  41. package/dist/src/execution/run-session-limits.js +1 -0
  42. package/dist/src/execution/runtime-context.js +1 -1
  43. package/dist/src/execution/sandbox/abort-bound-session.d.ts +6 -0
  44. package/dist/src/execution/sandbox/abort-bound-session.js +1 -0
  45. package/dist/src/execution/sandbox/active-handles.d.ts +29 -0
  46. package/dist/src/execution/sandbox/active-handles.js +1 -0
  47. package/dist/src/execution/sandbox/bindings/docker.d.ts +2 -2
  48. package/dist/src/execution/sandbox/bindings/docker.js +1 -1
  49. package/dist/src/execution/sandbox/bindings/just-bash-runtime.js +1 -1
  50. package/dist/src/execution/sandbox/bindings/local-backend-utils.d.ts +1 -1
  51. package/dist/src/execution/sandbox/bindings/local-backend-utils.js +1 -1
  52. package/dist/src/execution/sandbox/bindings/microsandbox-lifecycle.js +1 -1
  53. package/dist/src/execution/sandbox/bindings/microsandbox-provider-state.d.ts +11 -0
  54. package/dist/src/execution/sandbox/bindings/microsandbox-provider-state.js +1 -0
  55. package/dist/src/execution/sandbox/bindings/microsandbox-runtime.d.ts +7 -4
  56. package/dist/src/execution/sandbox/bindings/microsandbox-runtime.js +1 -1
  57. package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
  58. package/dist/src/execution/sandbox/ensure.js +1 -1
  59. package/dist/src/execution/sandbox/prewarm.js +1 -1
  60. package/dist/src/execution/sandbox/require-sandbox.d.ts +3 -1
  61. package/dist/src/execution/sandbox/require-sandbox.js +1 -1
  62. package/dist/src/execution/session-callback-step.d.ts +6 -0
  63. package/dist/src/execution/session-callback-step.js +1 -1
  64. package/dist/src/execution/session.d.ts +14 -3
  65. package/dist/src/execution/session.js +2 -4
  66. package/dist/src/execution/skills/instructions.d.ts +8 -4
  67. package/dist/src/execution/skills/instructions.js +2 -2
  68. package/dist/src/execution/subagent-tool.d.ts +7 -0
  69. package/dist/src/execution/subagent-tool.js +1 -1
  70. package/dist/src/execution/subagent-usage-span.d.ts +9 -0
  71. package/dist/src/execution/subagent-usage-span.js +1 -0
  72. package/dist/src/execution/tool-auth.d.ts +2 -1
  73. package/dist/src/execution/tool-auth.js +1 -1
  74. package/dist/src/execution/turn-execution-cursor.d.ts +2 -0
  75. package/dist/src/execution/turn-workflow.js +1 -1
  76. package/dist/src/execution/web-fetch/tool.d.ts +6 -1
  77. package/dist/src/execution/web-fetch/tool.js +1 -1
  78. package/dist/src/execution/workflow-entry.d.ts +1 -0
  79. package/dist/src/execution/workflow-entry.js +1 -1
  80. package/dist/src/execution/workflow-runtime.js +1 -1
  81. package/dist/src/execution/workflow-skill-root.d.ts +6 -0
  82. package/dist/src/execution/workflow-skill-root.js +1 -0
  83. package/dist/src/execution/workflow-steps.d.ts +3 -0
  84. package/dist/src/execution/workflow-steps.js +1 -1
  85. package/dist/src/harness/advertised-tools.d.ts +1 -0
  86. package/dist/src/harness/advertised-tools.js +1 -1
  87. package/dist/src/harness/attachment-staging.js +1 -1
  88. package/dist/src/harness/compaction.d.ts +1 -1
  89. package/dist/src/harness/compaction.js +1 -1
  90. package/dist/src/harness/emission.js +1 -1
  91. package/dist/src/harness/execute-tool.d.ts +2 -1
  92. package/dist/src/harness/input-requests.d.ts +8 -0
  93. package/dist/src/harness/input-requests.js +1 -1
  94. package/dist/src/harness/model-call-error.js +1 -1
  95. package/dist/src/harness/runtime-actions.js +1 -1
  96. package/dist/src/harness/session-limit-continuation.d.ts +55 -0
  97. package/dist/src/harness/session-limit-continuation.js +1 -0
  98. package/dist/src/harness/session-limit-enforcement.d.ts +55 -0
  99. package/dist/src/harness/session-limit-enforcement.js +1 -0
  100. package/dist/src/harness/step-hooks.d.ts +1 -1
  101. package/dist/src/harness/step-hooks.js +1 -1
  102. package/dist/src/harness/subagent-depth.d.ts +1 -4
  103. package/dist/src/harness/subagent-depth.js +1 -1
  104. package/dist/src/harness/subagent-token-budget.d.ts +14 -0
  105. package/dist/src/harness/subagent-token-budget.js +1 -0
  106. package/dist/src/harness/tool-loop.js +1 -1
  107. package/dist/src/harness/tools.d.ts +2 -3
  108. package/dist/src/harness/tools.js +1 -1
  109. package/dist/src/harness/turn-cancellation.d.ts +8 -0
  110. package/dist/src/harness/turn-cancellation.js +1 -0
  111. package/dist/src/harness/turn-tag-state.d.ts +33 -0
  112. package/dist/src/harness/turn-tag-state.js +1 -1
  113. package/dist/src/harness/types.d.ts +23 -4
  114. package/dist/src/harness/workflow-sandbox.d.ts +1 -0
  115. package/dist/src/harness/workflow-sandbox.js +1 -1
  116. package/dist/src/harness/workflow-subagent-limit.d.ts +38 -0
  117. package/dist/src/harness/workflow-subagent-limit.js +1 -0
  118. package/dist/src/harness/workflow-tool-description.d.ts +6 -1
  119. package/dist/src/harness/workflow-tool-description.js +5 -3
  120. package/dist/src/internal/application/package.js +1 -1
  121. package/dist/src/internal/authored-definition/core.js +1 -1
  122. package/dist/src/internal/authored-definition/schema-backed.js +1 -1
  123. package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
  124. package/dist/src/internal/nitro/host/sandbox-shutdown-plugin.d.ts +40 -0
  125. package/dist/src/internal/nitro/host/sandbox-shutdown-plugin.js +1 -0
  126. package/dist/src/internal/nitro/host/start-production-server.js +1 -1
  127. package/dist/src/protocol/message.d.ts +31 -2
  128. package/dist/src/protocol/message.js +2 -2
  129. package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +34 -3
  130. package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
  131. package/dist/src/public/channels/chat-sdk/index.d.ts +2 -0
  132. package/dist/src/public/channels/chat-sdk/index.js +1 -1
  133. package/dist/src/public/channels/chat-sdk/messageToUserContent.d.ts +13 -0
  134. package/dist/src/public/channels/chat-sdk/messageToUserContent.js +1 -0
  135. package/dist/src/public/channels/chat-sdk/notImplemented.d.ts +7 -0
  136. package/dist/src/public/channels/chat-sdk/notImplemented.js +1 -0
  137. package/dist/src/public/channels/slack/api.d.ts +14 -12
  138. package/dist/src/public/channels/slack/api.js +1 -1
  139. package/dist/src/public/definitions/approval.d.ts +4 -1
  140. package/dist/src/public/definitions/tool.d.ts +44 -0
  141. package/dist/src/public/definitions/tool.js +1 -1
  142. package/dist/src/public/tools/index.d.ts +1 -1
  143. package/dist/src/public/tools/index.js +1 -1
  144. package/dist/src/public/tools/internal.d.ts +3 -2
  145. package/dist/src/public/tools/internal.js +1 -1
  146. package/dist/src/runtime/actions/types.d.ts +9 -0
  147. package/dist/src/runtime/actions/types.js +1 -1
  148. package/dist/src/runtime/agent/bootstrap.d.ts +2 -0
  149. package/dist/src/runtime/agent/bootstrap.js +1 -1
  150. package/dist/src/runtime/connections/mcp-client.d.ts +2 -2
  151. package/dist/src/runtime/connections/mcp-client.js +1 -1
  152. package/dist/src/runtime/connections/openapi-client.d.ts +2 -2
  153. package/dist/src/runtime/connections/openapi-client.js +1 -1
  154. package/dist/src/runtime/connections/types.d.ts +6 -1
  155. package/dist/src/runtime/framework-tools/bash.js +1 -1
  156. package/dist/src/runtime/framework-tools/connection-search-dynamic.js +1 -1
  157. package/dist/src/runtime/framework-tools/glob.js +1 -1
  158. package/dist/src/runtime/framework-tools/grep.js +1 -1
  159. package/dist/src/runtime/framework-tools/read-file.js +1 -1
  160. package/dist/src/runtime/framework-tools/web-fetch.js +1 -1
  161. package/dist/src/runtime/framework-tools/write-file.js +1 -1
  162. package/dist/src/runtime/resolve-agent.js +1 -1
  163. package/dist/src/runtime/sandbox/keys.js +1 -1
  164. package/dist/src/runtime/sandbox/template-plan.js +1 -1
  165. package/dist/src/runtime/session-callback-route.js +1 -1
  166. package/dist/src/runtime/skills/sandbox-access.d.ts +1 -1
  167. package/dist/src/runtime/skills/sandbox-access.js +1 -1
  168. package/dist/src/runtime/workspace/seed-files.js +1 -1
  169. package/dist/src/sandbox/state.d.ts +0 -1
  170. package/dist/src/setup/scaffold/create/project.js +1 -1
  171. package/dist/src/setup/scaffold/create/web-template.d.ts +2 -2
  172. package/dist/src/setup/scaffold/create/web-template.js +77 -3
  173. package/dist/src/shared/agent-definition.d.ts +31 -3
  174. package/dist/src/shared/dynamic-tool-definition.d.ts +4 -1
  175. package/dist/src/shared/sandbox-backend.d.ts +7 -1
  176. package/dist/src/shared/skill-package.d.ts +2 -2
  177. package/dist/src/shared/skill-package.js +1 -1
  178. package/dist/src/shared/skill-paths.d.ts +28 -0
  179. package/dist/src/shared/skill-paths.js +2 -0
  180. package/dist/src/shared/token-usage.d.ts +22 -0
  181. package/dist/src/shared/token-usage.js +1 -0
  182. package/dist/src/shared/tool-definition.d.ts +1 -1
  183. package/dist/src/svelte/index.js +1 -1
  184. package/dist/src/svelte/use-eve-agent.js +1 -1
  185. package/dist/src/vue/index.js +1 -1
  186. package/dist/src/vue/use-eve-agent.js +1 -1
  187. package/docs/agent-config.md +32 -15
  188. package/docs/channels/chat-sdk.mdx +209 -0
  189. package/docs/channels/meta.json +1 -0
  190. package/docs/concepts/context-control.md +2 -2
  191. package/docs/concepts/default-harness.md +10 -0
  192. package/docs/concepts/sessions-runs-and-streaming.md +1 -1
  193. package/docs/guides/client/messages.mdx +4 -0
  194. package/docs/guides/client/streaming.mdx +17 -12
  195. package/docs/guides/dynamic-workflows.md +87 -0
  196. package/docs/guides/frontend/overview.mdx +5 -1
  197. package/docs/guides/meta.json +1 -0
  198. package/docs/guides/remote-agents.md +1 -0
  199. package/docs/reference/project-layout.md +5 -4
  200. package/docs/reference/typescript-api.md +26 -26
  201. package/docs/sandbox.mdx +4 -2
  202. package/docs/skills.mdx +3 -1
  203. package/docs/subagents.mdx +2 -1
  204. package/docs/tools/human-in-the-loop.md +1 -1
  205. package/docs/tools/overview.mdx +2 -0
  206. package/package.json +1 -1
@@ -52,13 +52,13 @@ When the task is novel or ambiguous, gather evidence first, then answer with the
52
52
  remaining uncertainty.
53
53
  ```
54
54
 
55
- Packaged skills are useful when you also want sibling files such as `references/`, `assets/`, or `scripts/` under the same skill directory. Those paths show up under the runtime workspace root, so the model can inspect them with the normal file or shell tools instead of pasting their content into the prompt.
55
+ Packaged skills are useful when you also want sibling files such as `references/`, `assets/`, or `scripts/` under the same skill directory. Those files are available under the runtime skill root, normally `$HOME/.agents/skills/<skill>/`. Relative references inside a `SKILL.md` resolve from that specific skill directory, so `references/checklist.md` means `$HOME/.agents/skills/<skill>/references/checklist.md` unless eve has fallen back to `/workspace/skills/<skill>/`.
56
56
 
57
57
  See [Skills](../skills) for the full authoring model and install notes.
58
58
 
59
59
  ## Put runtime files in the workspace, not the prompt
60
60
 
61
- eve does not inline the entire authored surface into the prompt. Instead, it gives the model a shallow workspace hint and runtime tools to inspect deeper when needed. Skill files are available under the active workspace root, and the model inspects them with the shared `bash` tool, which keeps prompts smaller and makes file and command work explicit.
61
+ eve does not inline the entire authored surface into the prompt. Instead, it gives the model a shallow workspace hint, a separate skill-root hint, and runtime tools to inspect deeper when needed. Skill package files are outside `/workspace` in the normal case, and the model inspects them with the shared `bash` tool, which keeps prompts smaller and makes file and command work explicit.
62
62
 
63
63
  See [Sandbox](../sandbox) for the workspace and sandbox model.
64
64
 
@@ -87,6 +87,16 @@ Three moves shape the harness. The right one depends on whether the model should
87
87
  - **Disable** when the model should not have the capability at all. A `disableTool()` sentinel removes the built-in, and the model never sees it. Reach for this to lock down `bash` or `web_fetch` in an agent that should not run shell commands or fetch arbitrary URLs.
88
88
  - **Author a new tool** when you want a capability the harness does not ship. Give it a fresh slug under `agent/tools/` and it joins the built-ins instead of replacing one. See [Tools](../tools) for the authoring model.
89
89
 
90
+ ## The opt-in `Workflow` tool
91
+
92
+ An experimental `Workflow` tool ships but stays off by default. To turn it on, re-export the opt-in marker from `agent/tools/workflow.ts`:
93
+
94
+ ```ts
95
+ export { ExperimentalWorkflow as default } from "eve/tools";
96
+ ```
97
+
98
+ With it on, the model can orchestrate the agent's own subagents from model-authored JavaScript, all as one durable step. The tool is root-only — delegated subagent sessions never see it — and one program may dispatch at most `limits.maxSubagents` subagent calls (default 100). See [Dynamic workflows](../guides/dynamic-workflows).
99
+
90
100
  ## What to read next
91
101
 
92
102
  - [Tools](../tools): define your own tools, gate them on approval, and shape their output with `toModelOutput`
@@ -38,7 +38,7 @@ The stream is newline-delimited JSON (NDJSON), one event per line:
38
38
  | ------------------------- | ---------------------------------------------------------------------------------------------------------------- |
39
39
  | `session.started` | A durable session was created. |
40
40
  | `turn.started` | A new turn began. |
41
- | `message.received` | An inbound user message was accepted. |
41
+ | `message.received` | An inbound user message was accepted; carries flattened text plus structured text/file parts. |
42
42
  | `step.started` | A model step began. |
43
43
  | `actions.requested` | The model requested one or more actions, including tool calls; calls stream before execution. |
44
44
  | `action.result` | A tool call returned. |
@@ -98,6 +98,10 @@ const response = await session.send({
98
98
  await response.result();
99
99
  ```
100
100
 
101
+ The stream confirms the turn with `message.received`. Its `data.message` remains the flattened
102
+ summary for compatibility, and `data.parts` contains structured text and file metadata for clients
103
+ that render attachments. File parts never include raw bytes or internal sandbox paths.
104
+
101
105
  ## Answer human input requests
102
106
 
103
107
  Tools can pause for approval or ask the user a question. The stream emits `input.requested` with one or more requests. Reply through the same session with `inputResponses`:
@@ -61,21 +61,26 @@ function handleEvent(event: HandleMessageStreamEvent) {
61
61
 
62
62
  The most common UI events are:
63
63
 
64
- | Event | Use |
65
- | -------------------- | ---------------------------------------------------------------- |
66
- | `message.received` | Confirm the user message landed. |
67
- | `reasoning.appended` | Render reasoning deltas when the model provides them. |
68
- | `message.appended` | Render assistant text deltas. |
69
- | `actions.requested` | Show tool calls as the model requests them, before execution. |
70
- | `action.result` | Show tool call results. |
71
- | `input.requested` | Pause the UI for approval or a question answer. |
72
- | `result.completed` | Read structured output from an [output schema](./output-schema). |
73
- | `session.waiting` | Enable the composer for the next turn. |
74
- | `session.completed` | Mark the conversation terminal. |
75
- | `session.failed` | Mark the conversation failed. |
64
+ | Event | Use |
65
+ | -------------------- | ------------------------------------------------------------------------------ |
66
+ | `message.received` | Confirm the user message landed; `data.parts` includes text and file metadata. |
67
+ | `reasoning.appended` | Render reasoning deltas when the model provides them. |
68
+ | `message.appended` | Render assistant text deltas. |
69
+ | `actions.requested` | Show tool calls as the model requests them, before execution. |
70
+ | `action.result` | Show tool call results. |
71
+ | `input.requested` | Pause the UI for approval or a question answer. |
72
+ | `result.completed` | Read structured output from an [output schema](./output-schema). |
73
+ | `session.waiting` | Enable the composer for the next turn. |
74
+ | `session.completed` | Mark the conversation terminal. |
75
+ | `session.failed` | Mark the conversation failed. |
76
76
 
77
77
  For the complete event table, see [Sessions, runs & streaming](../../concepts/sessions-runs-and-streaming).
78
78
 
79
+ When a submitted message includes attachments, `message.received.data.message` stays the
80
+ flattened compatibility summary, while `message.received.data.parts` carries renderable text and
81
+ file metadata. File parts never include raw bytes or internal sandbox paths; `url` appears only for
82
+ client-resolvable `http(s)` and `data:` URLs.
83
+
79
84
  ## Authorization pauses
80
85
 
81
86
  `authorization.required` is different from the normal `session.waiting` boundary. It means a connection needs OAuth or another authorization challenge before the parked turn can continue. Chat UIs should render the authorization prompt, disable ordinary text input for that session, and persist the event with the rest of the chat history.
@@ -0,0 +1,87 @@
1
+ ---
2
+ title: "Dynamic Workflows"
3
+ description: "The experimental Workflow tool: let the model orchestrate its own subagents from model-authored JavaScript as one durable step."
4
+ ---
5
+
6
+ The experimental `Workflow` tool lets the model write JavaScript that coordinates the agent's own subagents as a single durable step. The program can run them in sequence, feed one result into the next, fan out over a list, and combine the results. You enable the capability and the model decides and runs the orchestration.
7
+
8
+ A single turn can already call several subagents, and parallel tool calls dispatch concurrently. What a workflow adds is _programmatic_ coordination. The program decides how many subagents to run based on an earlier result, which output feeds which call, and how to combine everything. That is logic the model cannot express as a few one-off calls.
9
+
10
+ ## Enable the Workflow tool
11
+
12
+ Re-export the opt-in marker as the default export of `agent/tools/workflow.ts`. The marker name carries the "experimental" warning, but the tool the model actually sees is named `Workflow`.
13
+
14
+ ```ts title="agent/tools/workflow.ts"
15
+ export { ExperimentalWorkflow as default } from "eve/tools";
16
+ ```
17
+
18
+ Without that file, the `Workflow` tool stays off. It earns its keep only when the agent has subagents (or the built-in `agent`) worth coordinating:
19
+
20
+ ```ts title="agent/subagents/analyst/agent.ts"
21
+ import { defineAgent } from "eve";
22
+
23
+ export default defineAgent({
24
+ description: "Analyzes one metric: queries, computes, writes a short finding.",
25
+ model: "anthropic/claude-opus-4.8",
26
+ });
27
+ ```
28
+
29
+ When asked for a weekly business review, the model picks the metrics, runs one `analyst` per metric in parallel, and combines the findings. The program below is the kind of JavaScript the model authors. It fans `analyst` out over a runtime-decided list of metrics and merges the results:
30
+
31
+ ```js
32
+ const metrics = ["revenue", "signups", "churn"];
33
+ const findings = await Promise.all(
34
+ metrics.map((metric) => tools.analyst({ message: `Summarize last week's ${metric}.` })),
35
+ );
36
+ return findings.join("\n\n");
37
+ ```
38
+
39
+ Each `tools.analyst(...)` call dispatches a child subagent, so the parent stream records one `subagent.called` per metric and one `subagent.completed` as each finishes:
40
+
41
+ ```json
42
+ { "type": "subagent.called", "data": { "name": "analyst", "toolName": "analyst", "callId": "call_1", "childSessionId": "ses_a1", "sequence": 0 } }
43
+ { "type": "subagent.called", "data": { "name": "analyst", "toolName": "analyst", "callId": "call_2", "childSessionId": "ses_a2", "sequence": 1 } }
44
+ { "type": "subagent.called", "data": { "name": "analyst", "toolName": "analyst", "callId": "call_3", "childSessionId": "ses_a3", "sequence": 2 } }
45
+ { "type": "subagent.completed", "data": { "subagentName": "analyst", "callId": "call_1", "output": "..." } }
46
+ { "type": "subagent.completed", "data": { "subagentName": "analyst", "callId": "call_2", "output": "..." } }
47
+ { "type": "subagent.completed", "data": { "subagentName": "analyst", "callId": "call_3", "output": "..." } }
48
+ ```
49
+
50
+ ## What a workflow can orchestrate
51
+
52
+ A workflow reaches only this agent's own agents: the built-in `agent` (a copy of itself), declared [subagents](../subagents), and [remote agents](./remote-agents). That is the whole list. No files, network, shell, skills, or connections. A workflow is a coordination layer over subagents, not a place to do other work. Each call can still request structured output via `outputSchema`, exactly like a direct subagent delegation.
53
+
54
+ ## Caps on workflow-spawned subagents
55
+
56
+ Workflow orchestration is capped in two independent ways.
57
+
58
+ **Per-program call budget.** One Workflow program may dispatch at most `limits.maxSubagents` subagent calls in total, counted across the whole program — sequential and parallel calls alike. The default is 100. Calls beyond the budget do not start a child session; they resolve inside the program with a `WORKFLOW_SUBAGENT_LIMIT_REACHED` error result, and the budget is stated in the tool's description so the model sizes its fan-out to fit.
59
+
60
+ ```ts title="agent/agent.ts"
61
+ export default defineAgent({
62
+ model: "anthropic/claude-sonnet-5",
63
+ limits: {
64
+ maxSubagents: 4,
65
+ },
66
+ });
67
+ ```
68
+
69
+ **Root-only, one level of orchestration.** Only the root session ever sees the `Workflow` tool. The subagents a workflow spawns are ordinary delegated child sessions: they never receive the `Workflow` tool themselves, so a workflow cannot recursively spawn more workflows. Direct (non-workflow) delegation by those children stays subject to the usual `limits.maxSubagentDepth` cap (see [Subagents](../subagents)).
70
+
71
+ ## Where the JavaScript runs
72
+
73
+ The orchestration code never touches the agent's process. The runtime hands the program text to a small isolated JavaScript engine (a QuickJS sandbox) and runs it there. Nothing from the host realm crosses in, so there is no `process`, no `globalThis` from the agent, and no `import`/`require`. The program can reach exactly two things, the agent functions bridged in as `tools.<name>` and the ordinary language built-ins.
74
+
75
+ That is an allowlist, not a denylist. The sandbox cannot read files, open a socket, or see an environment variable because those are not present, not because each one is blocked in turn. When the program calls an agent function, that call bridges back out to the runtime, which dispatches it exactly like a direct delegation. The orchestration glue stays inside the sandbox.
76
+
77
+ ## Durability, approvals, and observability
78
+
79
+ - **Durable.** The whole orchestration counts as one step. Subagents dispatched together run concurrently, and if a run parks (suspends durably without holding compute; see [Execution model & durability](../concepts/execution-model-and-durability)) on a long-running or human-gated child, it resumes where it left off after a restart.
80
+ - **Approval-safe.** A subagent that needs human approval (HITL, human-in-the-loop) mid-run surfaces its request to the user, and the workflow picks back up once that is answered, same as direct delegation.
81
+ - **Observable.** Every orchestrated subagent emits the usual `subagent.called` / `subagent.completed` events on the parent stream and gets its own child session and stream. The telemetry matches direct delegation, so existing dashboards and cost attribution keep working.
82
+
83
+ ## What to read next
84
+
85
+ - Declare the subagents a workflow orchestrates → [Subagents](../subagents)
86
+ - Call another deployment as one of those agents → [Remote agents](./remote-agents)
87
+ - The `agent/tools/` opt-in mechanism → [Default harness](../concepts/default-harness)
@@ -74,7 +74,7 @@ export function Chat() {
74
74
 
75
75
  Most chat UIs only need `data.messages` and `status`. Drop down to `events` when you need the authoritative wire events directly, for example to persist an audit log or build a custom projection.
76
76
 
77
- `data.messages` are `EveMessage[]` following the AI SDK `UIMessage` convention, so they drop straight into any AI SDK UI primitive that accepts a `UIMessage[]`. Parts include user text, assistant text, reasoning, tool calls, tool results, input requests, and connection authorization prompts.
77
+ `data.messages` are `EveMessage[]` following the AI SDK `UIMessage` convention, so they drop straight into any AI SDK UI primitive that accepts a `UIMessage[]`. Parts include user text, user file attachments, assistant text, reasoning, tool calls, tool results, input requests, and connection authorization prompts.
78
78
 
79
79
  ## Sending and streaming
80
80
 
@@ -98,6 +98,10 @@ await agent.send({
98
98
 
99
99
  Assistant text, reasoning, tool calls, and tool results stream into `data` as they arrive, and `status` moves from `ready` to `submitted` to `streaming` and back. Call `stop()` to abort the active request, and `reset()` to clear local state so the next send starts a fresh durable session.
100
100
 
101
+ After eve confirms an attachment turn with `message.received`, the default reducer projects each
102
+ received attachment as a `file` part on the user message. The part includes `mediaType`, optional
103
+ `filename` and `size`, and a `url` only when the original attachment was browser-resolvable.
104
+
101
105
  ## Human-in-the-loop prompts
102
106
 
103
107
  Tools opt into approval with `approval`, and the model can also ask a question with `ask_question` — see [Human-in-the-loop](/docs/human-in-the-loop) for the server-side model. Either way the stream emits an `input.requested` event, and the pending request rides on a `dynamic-tool` part of the latest message at `part.toolMetadata?.eve?.inputRequest`. Read it, then answer through the same session with `send()`:
@@ -8,6 +8,7 @@
8
8
  "session-context",
9
9
  "state",
10
10
  "dynamic-capabilities",
11
+ "dynamic-workflows",
11
12
  "remote-agents",
12
13
  "dev-tui",
13
14
  "frontend",
@@ -60,4 +60,5 @@ Both failure paths surface to the parent as a failed tool result, so the caller
60
60
  ## What to read next
61
61
 
62
62
  - Local delegation and the isolation boundary → [Subagents](../subagents)
63
+ - Have the model orchestrate remote agents programmatically → [Dynamic workflows](./dynamic-workflows)
63
64
  - Securing the receiving deployment → [Auth & route protection](./auth-and-route-protection)
@@ -54,7 +54,7 @@ The Subagents column states whether a local subagent (`subagents/<id>/`) can aut
54
54
  | `channels/` | HTTP / messaging entrypoints | No | Root-only. |
55
55
  | `connections/` | External service connections (MCP, OpenAPI) | Yes | One connection per file; name derived from filename. |
56
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/...`. |
57
+ | `skills/` | On-demand procedures and capability packs | Yes | Flat markdown, module-backed skills, or packaged skills. Seeded into `$HOME/.agents/skills/...`, with `/workspace/skills/...` as a fallback if `$HOME` is unavailable. |
58
58
  | `lib/` | Shared authored helper code | Yes | Import-only; not mounted into the workspace. |
59
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
60
  | `sandbox/workspace/**` | Files seeded into the sandbox | Yes | Mirrored into `/workspace/...` at session bootstrap. |
@@ -62,13 +62,14 @@ The Subagents column states whether a local subagent (`subagents/<id>/`) can aut
62
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
63
  | `subagents/` | Specialist child agents | Yes | Each child is its own local package under `subagents/<id>/`. Nested subagents are supported. |
64
64
 
65
- ## What reaches the runtime workspace
65
+ ## What reaches the runtime sandbox
66
66
 
67
- eve does not mount the whole tree. Only two sources land in the sandbox workspace:
67
+ eve does not mount the whole tree. Authored workspace files land in the sandbox workspace:
68
68
 
69
- - `skills/` files → `/workspace/skills/...`
70
69
  - `agent/sandbox/workspace/**` → `/workspace/...` at session bootstrap
71
70
 
71
+ Skill files land outside the workspace, under `$HOME/.agents/skills/...`. If `$HOME` is unavailable, eve falls back to `/workspace/skills/...`. Packaged skill references such as `references/checklist.md` resolve relative to the directory containing that skill's `SKILL.md`.
72
+
72
73
  Everything in `lib/` stays import-only source code and never reaches the workspace.
73
74
 
74
75
  ## Local subagent layout
@@ -52,7 +52,7 @@ export default defineTool({
52
52
  | `mockModel` | `eve/evals` | Deterministic fixture agent models | [Evals](../evals/overview) |
53
53
  | `useEveAgent` | `eve/react`, `eve/vue`, `eve/svelte` | frontend | [Frontend](../guides/frontend/overview) |
54
54
 
55
- A few non-`define*` helpers round out the set: `disableTool` from `eve/tools` (see [Default harness](../concepts/default-harness)), the route verbs `GET`/`POST`/`PUT`/`PATCH`/`DELETE`/`WS` from `eve/channels`, the approval policies `always`/`once`/`never` from `eve/tools/approval`, and the channel auth helpers `localDev`/`vercelOidc`/`placeholderAuth` from `eve/channels/auth`. To wrap a built-in tool, import its default value from `eve/tools/defaults` (`bash`, `readFile`, `writeFile`, `glob`, `grep`, `webFetch`, `webSearch`, `todo`, `loadSkill`). `AgentReasoningDefinition` is exported from `eve` for the top-level `defineAgent({ reasoning })` setting. `AgentLimitsDefinition` is exported for `defineAgent({ limits })`. `AgentWorkflowDefinition` and `AgentWorkflowWorldDefinition` are exported from `eve` for the `defineAgent({ experimental: { workflow } })` config shape.
55
+ A few non-`define*` helpers round out the set: `disableTool` and `ExperimentalWorkflow` from `eve/tools` (see [Default harness](../concepts/default-harness)), the route verbs `GET`/`POST`/`PUT`/`PATCH`/`DELETE`/`WS` from `eve/channels`, the approval policies `always`/`once`/`never` from `eve/tools/approval`, and the channel auth helpers `localDev`/`vercelOidc`/`placeholderAuth` from `eve/channels/auth`. To wrap a built-in tool, import its default value from `eve/tools/defaults` (`bash`, `readFile`, `writeFile`, `glob`, `grep`, `webFetch`, `webSearch`, `todo`, `loadSkill`). `AgentReasoningDefinition` is exported from `eve` for the top-level `defineAgent({ reasoning })` setting. `AgentLimitsDefinition` is exported for `defineAgent({ limits })`. `AgentWorkflowDefinition` and `AgentWorkflowWorldDefinition` are exported from `eve` for the `defineAgent({ experimental: { workflow } })` config shape.
56
56
 
57
57
  ## Runtime context (`ctx`)
58
58
 
@@ -68,31 +68,31 @@ A few non-`define*` helpers round out the set: `disableTool` from `eve/tools` (s
68
68
 
69
69
  ## Imports at a glance
70
70
 
71
- | Import | Holds |
72
- | ----------------------------------------------------------- | --------------------------------------------------------- |
73
- | `eve` | `defineAgent`, `defineRemoteAgent`, agent config types |
74
- | `eve/tools` | `defineTool`, `defineDynamic`, `disableTool` |
75
- | `eve/tools/defaults` | the built-in tools as plain values |
76
- | `eve/tools/approval` | `always`, `once`, `never` |
77
- | `eve/connections` | `defineMcpClientConnection`, `defineOpenAPIConnection` |
78
- | `eve/channels` | `defineChannel`, route verbs |
79
- | `eve/channels/eve` | `eveChannel` |
80
- | `eve/channels/auth` | `localDev`, `vercelOidc`, `placeholderAuth` |
81
- | `eve/channels/{slack,discord,teams,telegram,twilio,github}` | platform channel factories |
82
- | `eve/hooks` | `defineHook` |
83
- | `eve/schedules` | `defineSchedule` |
84
- | `eve/skills` | `defineSkill`, `defineDynamic` |
85
- | `eve/instructions` | `defineInstructions`, `defineDynamic` |
86
- | `eve/context` | `defineState`, session and state types |
87
- | `eve/sandbox` | `defineSandbox`, backends |
88
- | `eve/instrumentation` | `defineInstrumentation`, `isChannel` |
89
- | `eve/evals` | `defineEval`, `defineEvalConfig`, `mockModel`, eval types |
90
- | `eve/evals/expect` | `includes`, `equals`, `matches`, `similarity` |
91
- | `eve/evals/reporters` | `Braintrust`, `JUnit`, `EvalReporter` |
92
- | `eve/evals/loaders` | `loadJson`, `loadYaml` |
93
- | `eve/react`, `eve/vue`, `eve/svelte` | `useEveAgent` |
94
- | `eve/next`, `eve/nuxt`, `eve/sveltekit` | framework bundler plugins |
95
- | [`eve/client`](../guides/client/overview) | `Client`, `ClientSession` |
71
+ | Import | Holds |
72
+ | ----------------------------------------------------------- | -------------------------------------------------------------------- |
73
+ | `eve` | `defineAgent`, `defineRemoteAgent`, agent config types |
74
+ | `eve/tools` | `defineTool`, `defineDynamic`, `disableTool`, `ExperimentalWorkflow` |
75
+ | `eve/tools/defaults` | the built-in tools as plain values |
76
+ | `eve/tools/approval` | `always`, `once`, `never` |
77
+ | `eve/connections` | `defineMcpClientConnection`, `defineOpenAPIConnection` |
78
+ | `eve/channels` | `defineChannel`, route verbs |
79
+ | `eve/channels/eve` | `eveChannel` |
80
+ | `eve/channels/auth` | `localDev`, `vercelOidc`, `placeholderAuth` |
81
+ | `eve/channels/{slack,discord,teams,telegram,twilio,github}` | platform channel factories |
82
+ | `eve/hooks` | `defineHook` |
83
+ | `eve/schedules` | `defineSchedule` |
84
+ | `eve/skills` | `defineSkill`, `defineDynamic` |
85
+ | `eve/instructions` | `defineInstructions`, `defineDynamic` |
86
+ | `eve/context` | `defineState`, session and state types |
87
+ | `eve/sandbox` | `defineSandbox`, backends |
88
+ | `eve/instrumentation` | `defineInstrumentation`, `isChannel` |
89
+ | `eve/evals` | `defineEval`, `defineEvalConfig`, `mockModel`, eval types |
90
+ | `eve/evals/expect` | `includes`, `equals`, `matches`, `similarity` |
91
+ | `eve/evals/reporters` | `Braintrust`, `JUnit`, `EvalReporter` |
92
+ | `eve/evals/loaders` | `loadJson`, `loadYaml` |
93
+ | `eve/react`, `eve/vue`, `eve/svelte` | `useEveAgent` |
94
+ | `eve/next`, `eve/nuxt`, `eve/sveltekit` | framework bundler plugins |
95
+ | [`eve/client`](../guides/client/overview) | `Client`, `ClientSession` |
96
96
 
97
97
  Exported types ship from the same entrypoint as the helper they describe (for example `ToolDefinition` and `ToolContext` from `eve/tools`). For the exhaustive list, read `packages/eve/src/public/index.ts`.
98
98
 
package/docs/sandbox.mdx CHANGED
@@ -82,7 +82,7 @@ agent/sandbox/
82
82
  scripts/run.sh ← lands at /workspace/scripts/run.sh
83
83
  ```
84
84
 
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.
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. `agent/skills/` files are materialized separately under `$HOME/.agents/skills/`, so `agent/sandbox/workspace/skills/...` is an ordinary workspace subtree when you choose to author one.
86
86
 
87
87
  ## Overriding the sandbox
88
88
 
@@ -157,7 +157,7 @@ export default defineSandbox({
157
157
 
158
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.
159
159
 
160
- You can also write your own backend. A `SandboxBackend` is an adapter object with a `name`, a `create`, and an optional `prewarm`. It can point at your own container runner, VM pool, internal sandbox service, or another isolation layer, as long as it returns the `SandboxSession` operations eve needs. See the `SandboxBackend*` types on `eve/sandbox`.
160
+ You can also write your own backend. A `SandboxBackend` is an adapter object with a `name`, a `create`, and an optional `prewarm`. It can point at your own container runner, VM pool, internal sandbox service, or another isolation layer, as long as it returns the `SandboxSession` operations eve needs. Handles returned by `create` implement `shutdown()`, which stops the underlying compute at server shutdown. See the `SandboxBackend*` types on `eve/sandbox`.
161
161
 
162
162
  ## Lifecycle
163
163
 
@@ -185,6 +185,8 @@ export default defineSandbox({
185
185
 
186
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.
187
187
 
188
+ When the eve server stops, no sandbox compute outlives it. `eve dev` stops the sandboxes it started when the dev server closes, and a self-hosted production server stops every open sandbox on shutdown (`SIGTERM`/`SIGINT`). Session state persists across the stop — the next server start reattaches each durable session from its stopped container, VM, or snapshot. Custom `SandboxBackend` adapters participate through the handle's `shutdown()` method: stop the underlying compute, keeping the session reattachable from persisted state where the backend supports it.
189
+
188
190
  ## Network policy
189
191
 
190
192
  Egress rules go on the backend factory or in `onSession`'s `use()`. There are three forms:
package/docs/skills.mdx CHANGED
@@ -9,6 +9,8 @@ A skill is a model-loadable procedure that follows the `SKILL.md` convention. It
9
9
 
10
10
  eve scans the files under `agent/skills/` and exposes each one's description to the model alongside a framework-owned `load_skill` tool. When a request matches a skill's description (or you name the skill outright), the model calls `load_skill`, and eve appends that skill's markdown to the active turn's context.
11
11
 
12
+ At runtime, skill package files are placed under `$HOME/.agents/skills/<skill>/`. If `$HOME` is unavailable in a sandbox, eve falls back to `/workspace/skills/<skill>/`. `load_skill` reads `SKILL.md` automatically; any sibling references inside that file, such as `references/checklist.md`, are relative to the directory containing that specific `SKILL.md`.
13
+
12
14
  The description is a routing hint, not a label. Write it as the task that should trigger activation:
13
15
 
14
16
  ```md
@@ -68,7 +70,7 @@ const research = ctx.getSkill("research");
68
70
  const checklist = await research.file("references/checklist.md").text();
69
71
  ```
70
72
 
71
- The handle exposes the skill's `name` and `file(relativePath)`; file content is read lazily from the active sandbox.
73
+ The handle exposes the skill's `name` and `file(relativePath)`; file content is read lazily from the active sandbox, relative to that skill package directory.
72
74
 
73
75
  ## Dynamic skills
74
76
 
@@ -94,7 +94,7 @@ at depths 1 through 4; a session already at depth 4 cannot delegate again.
94
94
 
95
95
  At the configured depth, eve stops advertising subagent tools, including declared local subagents, remote-agent tools, the built-in `agent` tool, and the `Workflow` orchestration tool when it would only expose subagents. If a stale or forced subagent call still reaches execution, eve blocks it and returns an error tool result instead of starting another child session.
96
96
 
97
- `Workflow` is root-only. Delegated subagent sessions can still call their own visible subagent tools until the depth cap, but they do not receive the `Workflow` orchestration wrapper.
97
+ `Workflow` is root-only. Delegated subagent sessions can still call their own visible subagent tools until the depth cap, but they do not receive the `Workflow` orchestration wrapper. The number of subagent calls one Workflow program may dispatch is capped separately by `limits.maxSubagents` (default 100); see [Dynamic workflows](./guides/dynamic-workflows).
98
98
 
99
99
  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>__<tool>`), it carries no namespace, so the model, approvals, logs, and evals all reference it by that name. Its input schema is:
100
100
 
@@ -118,3 +118,4 @@ Split out a subagent when the task needs a different prompt or specialist role,
118
118
  ## What to read next
119
119
 
120
120
  - [Remote agents](./guides/remote-agents): call another eve deployment as a subagent.
121
+ - [Dynamic workflows](./guides/dynamic-workflows): have the model orchestrate its subagents programmatically (fan-out, map-reduce).
@@ -38,7 +38,7 @@ export default defineTool({
38
38
 
39
39
  By default, omitted `approval` 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.
40
40
 
41
- When the decision depends on the input, pass your own policy instead of a helper. It receives the same session context as tool execution, plus `{ toolName, toolInput, approvedTools }`, and returns an AI SDK 7 approval status synchronously or as a promise. Use `ctx.session.auth.current` to guard by the caller of the current turn and `ctx.session.auth.initiator` to guard by the caller that created the session. Return `"user-approval"` to pause for a person or `"not-applicable"` to continue without a prompt. `toolInput` can be undefined, so guard the access. This policy denies cross-tenant calls, then requires approval only when an amount crosses a threshold:
41
+ When the decision depends on the input, pass your own policy instead of a helper. It receives the same session context as tool execution, plus `{ toolName, toolInput, approvedTools, callId }`, and returns an AI SDK 7 approval status synchronously or as a promise. Use `ctx.session.auth.current` to guard by the caller of the current turn and `ctx.session.auth.initiator` to guard by the caller that created the session. Return `"user-approval"` to pause for a person or `"not-applicable"` to continue without a prompt. `toolInput` can be undefined, so guard the access. This policy denies cross-tenant calls, then requires approval only when an amount crosses a threshold:
42
42
 
43
43
  ```ts
44
44
  approval: ({ session, toolInput }) => {
@@ -37,6 +37,8 @@ When a tool returns structured data, add an optional `outputSchema`. With Zod or
37
37
  `execute` gets a `ctx` carrying the runtime accessors:
38
38
 
39
39
  - `ctx.session`: session metadata, turn, auth, parent lineage.
40
+ - `ctx.callId`: the id of the current tool call, carried by the call's [stream events](/docs/concepts/sessions-runs-and-streaming) and approval context.
41
+ - `ctx.abortSignal`: aborts when the active turn is cancelled. Pass it to cancellation-aware work; sandbox sessions from `ctx.getSandbox()` are already bound to it.
40
42
  - `ctx.getSandbox()`: the live [sandbox](/docs/sandbox) handle.
41
43
  - `ctx.getSkill(id)`: read a packaged [skill](/docs/skills)'s metadata and files.
42
44
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eve",
3
- "version": "0.19.0",
3
+ "version": "0.21.0",
4
4
  "private": false,
5
5
  "description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
6
6
  "keywords": [