eve 0.20.0 → 0.21.1

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 (139) hide show
  1. package/CHANGELOG.md +22 -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/client/index.d.ts +1 -1
  6. package/dist/src/client/message-reducer-types.d.ts +11 -3
  7. package/dist/src/client/message-reducer.js +1 -1
  8. package/dist/src/compiler/manifest.js +1 -1
  9. package/dist/src/compiler/normalize-agent-config.js +1 -1
  10. package/dist/src/compiler/workspace-resources.js +1 -1
  11. package/dist/src/context/dynamic-skill-lifecycle.js +1 -1
  12. package/dist/src/context/keys.d.ts +0 -1
  13. package/dist/src/context/keys.js +1 -1
  14. package/dist/src/discover/sandbox.d.ts +0 -6
  15. package/dist/src/discover/sandbox.js +1 -1
  16. package/dist/src/evals/cli/eval.js +2 -2
  17. package/dist/src/execution/create-session-step.d.ts +2 -1
  18. package/dist/src/execution/create-session-step.js +1 -1
  19. package/dist/src/execution/delegated-parent-notification.d.ts +6 -0
  20. package/dist/src/execution/delegated-parent-notification.js +1 -1
  21. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  22. package/dist/src/execution/dispatch-workflow-runtime-actions-step.js +1 -1
  23. package/dist/src/execution/durable-session-store.d.ts +1 -0
  24. package/dist/src/execution/next-driver-action.d.ts +3 -0
  25. package/dist/src/execution/node-step.d.ts +6 -0
  26. package/dist/src/execution/node-step.js +1 -1
  27. package/dist/src/execution/run-session-limits.d.ts +21 -0
  28. package/dist/src/execution/run-session-limits.js +1 -0
  29. package/dist/src/execution/runtime-context.js +1 -1
  30. package/dist/src/execution/sandbox/bindings/local-backend-utils.d.ts +1 -1
  31. package/dist/src/execution/sandbox/bindings/local-backend-utils.js +1 -1
  32. package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
  33. package/dist/src/execution/sandbox/ensure.js +1 -1
  34. package/dist/src/execution/sandbox/prewarm.js +1 -1
  35. package/dist/src/execution/session-callback-step.d.ts +6 -0
  36. package/dist/src/execution/session-callback-step.js +1 -1
  37. package/dist/src/execution/session.d.ts +14 -3
  38. package/dist/src/execution/session.js +2 -4
  39. package/dist/src/execution/skills/instructions.d.ts +8 -4
  40. package/dist/src/execution/skills/instructions.js +2 -2
  41. package/dist/src/execution/subagent-tool.d.ts +7 -0
  42. package/dist/src/execution/subagent-tool.js +1 -1
  43. package/dist/src/execution/subagent-usage-span.d.ts +9 -0
  44. package/dist/src/execution/subagent-usage-span.js +1 -0
  45. package/dist/src/execution/turn-execution-cursor.d.ts +2 -0
  46. package/dist/src/execution/turn-workflow.js +1 -1
  47. package/dist/src/execution/workflow-entry.d.ts +1 -0
  48. package/dist/src/execution/workflow-entry.js +1 -1
  49. package/dist/src/execution/workflow-runtime.js +1 -1
  50. package/dist/src/execution/workflow-skill-root.d.ts +6 -0
  51. package/dist/src/execution/workflow-skill-root.js +1 -0
  52. package/dist/src/execution/workflow-steps.d.ts +3 -0
  53. package/dist/src/execution/workflow-steps.js +1 -1
  54. package/dist/src/harness/advertised-tools.d.ts +1 -0
  55. package/dist/src/harness/advertised-tools.js +1 -1
  56. package/dist/src/harness/input-requests.d.ts +8 -0
  57. package/dist/src/harness/input-requests.js +1 -1
  58. package/dist/src/harness/runtime-actions.js +1 -1
  59. package/dist/src/harness/session-limit-continuation.d.ts +55 -0
  60. package/dist/src/harness/session-limit-continuation.js +1 -0
  61. package/dist/src/harness/session-limit-enforcement.d.ts +55 -0
  62. package/dist/src/harness/session-limit-enforcement.js +1 -0
  63. package/dist/src/harness/subagent-depth.d.ts +1 -4
  64. package/dist/src/harness/subagent-depth.js +1 -1
  65. package/dist/src/harness/subagent-token-budget.d.ts +14 -0
  66. package/dist/src/harness/subagent-token-budget.js +1 -0
  67. package/dist/src/harness/tool-loop.js +1 -1
  68. package/dist/src/harness/turn-tag-state.d.ts +31 -0
  69. package/dist/src/harness/turn-tag-state.js +1 -1
  70. package/dist/src/harness/types.d.ts +21 -4
  71. package/dist/src/harness/workflow-sandbox.d.ts +1 -0
  72. package/dist/src/harness/workflow-sandbox.js +1 -1
  73. package/dist/src/harness/workflow-subagent-limit.d.ts +38 -0
  74. package/dist/src/harness/workflow-subagent-limit.js +1 -0
  75. package/dist/src/harness/workflow-tool-description.d.ts +6 -1
  76. package/dist/src/harness/workflow-tool-description.js +5 -3
  77. package/dist/src/internal/application/package.js +1 -1
  78. package/dist/src/internal/authored-definition/core.js +1 -1
  79. package/dist/src/internal/authored-definition/schema-backed.js +1 -1
  80. package/dist/src/internal/nitro/host/sandbox-shutdown-plugin.js +1 -1
  81. package/dist/src/protocol/message.d.ts +19 -2
  82. package/dist/src/protocol/message.js +2 -2
  83. package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +34 -3
  84. package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
  85. package/dist/src/public/channels/chat-sdk/index.d.ts +2 -0
  86. package/dist/src/public/channels/chat-sdk/index.js +1 -1
  87. package/dist/src/public/channels/chat-sdk/messageToUserContent.d.ts +13 -0
  88. package/dist/src/public/channels/chat-sdk/messageToUserContent.js +1 -0
  89. package/dist/src/public/channels/chat-sdk/notImplemented.d.ts +7 -0
  90. package/dist/src/public/channels/chat-sdk/notImplemented.js +1 -0
  91. package/dist/src/public/channels/slack/api.d.ts +14 -12
  92. package/dist/src/public/channels/slack/api.js +1 -1
  93. package/dist/src/public/definitions/tool.d.ts +37 -0
  94. package/dist/src/public/definitions/tool.js +1 -1
  95. package/dist/src/public/tools/index.d.ts +1 -1
  96. package/dist/src/public/tools/index.js +1 -1
  97. package/dist/src/runtime/actions/types.d.ts +9 -0
  98. package/dist/src/runtime/actions/types.js +1 -1
  99. package/dist/src/runtime/agent/bootstrap.d.ts +2 -0
  100. package/dist/src/runtime/agent/bootstrap.js +1 -1
  101. package/dist/src/runtime/resolve-agent.js +1 -1
  102. package/dist/src/runtime/sandbox/keys.js +1 -1
  103. package/dist/src/runtime/sandbox/template-plan.js +1 -1
  104. package/dist/src/runtime/session-callback-route.js +1 -1
  105. package/dist/src/runtime/skills/sandbox-access.d.ts +1 -1
  106. package/dist/src/runtime/skills/sandbox-access.js +1 -1
  107. package/dist/src/runtime/workspace/seed-files.js +1 -1
  108. package/dist/src/setup/scaffold/create/project.js +1 -1
  109. package/dist/src/setup/scaffold/create/web-template.d.ts +2 -2
  110. package/dist/src/setup/scaffold/create/web-template.js +77 -3
  111. package/dist/src/shared/agent-definition.d.ts +31 -3
  112. package/dist/src/shared/skill-package.d.ts +2 -2
  113. package/dist/src/shared/skill-package.js +1 -1
  114. package/dist/src/shared/skill-paths.d.ts +28 -0
  115. package/dist/src/shared/skill-paths.js +2 -0
  116. package/dist/src/shared/token-usage.d.ts +22 -0
  117. package/dist/src/shared/token-usage.js +1 -0
  118. package/dist/src/svelte/index.js +1 -1
  119. package/dist/src/svelte/use-eve-agent.js +1 -1
  120. package/dist/src/vue/index.js +1 -1
  121. package/dist/src/vue/use-eve-agent.js +1 -1
  122. package/docs/agent-config.md +32 -15
  123. package/docs/channels/chat-sdk.mdx +209 -0
  124. package/docs/channels/meta.json +1 -0
  125. package/docs/concepts/context-control.md +2 -2
  126. package/docs/concepts/default-harness.md +10 -0
  127. package/docs/concepts/sessions-runs-and-streaming.md +1 -1
  128. package/docs/guides/client/messages.mdx +4 -0
  129. package/docs/guides/client/streaming.mdx +17 -12
  130. package/docs/guides/dynamic-workflows.md +87 -0
  131. package/docs/guides/frontend/overview.mdx +5 -1
  132. package/docs/guides/meta.json +1 -0
  133. package/docs/guides/remote-agents.md +1 -0
  134. package/docs/reference/project-layout.md +5 -4
  135. package/docs/reference/typescript-api.md +26 -26
  136. package/docs/sandbox.mdx +1 -1
  137. package/docs/skills.mdx +3 -1
  138. package/docs/subagents.mdx +2 -1
  139. package/package.json +1 -1
@@ -93,13 +93,30 @@ export default defineAgent({
93
93
 
94
94
  Input and output budgets are checked independently. The model call that crosses
95
95
  either limit is allowed to finish because providers only report exact token
96
- usage after a call completes. Follow-up model calls in the same session fail
97
- with `SESSION_TOKEN_LIMIT_REACHED`.
98
-
99
- When `maxInputTokensPerSession` is omitted, eve applies a default input budget:
100
- `40_000_000` provider-reported input tokens for root sessions and `5_000_000`
101
- for delegated subagent sessions. `maxOutputTokensPerSession` is unset unless
102
- configured.
96
+ usage after a call completes. Before the next model call, eve pauses the
97
+ session and sends a deterministic continuation prompt with two options:
98
+ **Continue** grants a fresh budget window of the configured size (both input
99
+ and output windows reset together), and **Stop** ends the session gracefully
100
+ (`session.completed`) declining is a user decision, not an error. A reply
101
+ that answers neither option re-raises the prompt; the reply stays in history
102
+ and is processed once the budget is granted.
103
+
104
+ Sessions that cannot reach a human — task-mode runs such as schedules and
105
+ subagents without input proxying — skip the prompt and fail the next model
106
+ call with `SESSION_TOKEN_LIMIT_REACHED`.
107
+
108
+ When `maxInputTokensPerSession` is omitted, root sessions apply a default
109
+ input budget of `40_000_000` provider-reported input tokens.
110
+ `maxOutputTokensPerSession` is unset unless configured. Setting either limit
111
+ to `false` uncaps that axis — the session never stops on it.
112
+
113
+ Delegated subagent sessions have no fixed default. Each child receives a
114
+ share of the delegating parent's remaining quota at dispatch time — the
115
+ remainder (limit minus accumulated usage) split evenly across the batch's
116
+ local subagent calls — and a completed child's usage counts against the
117
+ parent's quota, so a delegation tree can never outspend the budget configured
118
+ at its root. An authored child limit applies only when it is tighter than the
119
+ parent's grant; an uncapped parent delegates uncapped children.
103
120
 
104
121
  ## Workflow world
105
122
 
@@ -142,14 +159,14 @@ installed package must stay external in hosted output, list it in
142
159
 
143
160
  `defineAgent` takes a few more fields, all optional. For the exported types, see the [TypeScript API](./reference/typescript-api).
144
161
 
145
- | Field | Type | Default | Description |
146
- | -------------- | --------------------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
147
- | `reasoning` | `AgentReasoningDefinition` | provider default | Provider-agnostic reasoning effort forwarded to the agent's turn model calls. |
148
- | `modelOptions` | `AgentModelOptionsDefinition` | none | Provider option overrides forwarded to the model call. |
149
- | `limits` | `AgentLimitsDefinition` | field-specific | Framework-owned runtime limits. `maxSubagentDepth` defaults to `3`; `maxInputTokensPerSession` defaults to `40_000_000` for root sessions and `5_000_000` for delegated subagent sessions; `maxOutputTokensPerSession` is unset unless configured. |
150
- | `experimental` | `{ workflow?: { world?: string } }` | unset | Opt-in settings that can change or disappear in any release. Treat them as unstable. `workflow.world` selects the Workflow world package backing session state, queues, hooks, and streams on the root agent. |
151
- | `outputSchema` | Standard Schema or a JSON Schema object | none | Structured return type for task-mode runs (a subagent, schedule, or remote job). Interactive conversation turns ignore it unless the client supplies a per-message schema. |
152
- | `build` | `{ externalDependencies?: string[] }` | none | Hosted-build packaging controls. `externalDependencies` keeps listed packages external while eve compiles authored modules such as tools and channels, and traces those packages into the hosted output. |
162
+ | Field | Type | Default | Description |
163
+ | -------------- | --------------------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
164
+ | `reasoning` | `AgentReasoningDefinition` | provider default | Provider-agnostic reasoning effort forwarded to the agent's turn model calls. |
165
+ | `modelOptions` | `AgentModelOptionsDefinition` | none | Provider option overrides forwarded to the model call. |
166
+ | `limits` | `AgentLimitsDefinition` | field-specific | Framework-owned runtime limits. `maxSubagentDepth` defaults to `3`; `maxInputTokensPerSession` defaults to `40_000_000` for root sessions, and delegated subagent sessions inherit the parent's remaining quota; `maxOutputTokensPerSession` is unset unless configured; `false` uncaps a session token limit. |
167
+ | `experimental` | `{ workflow?: { world?: string } }` | unset | Opt-in settings that can change or disappear in any release. Treat them as unstable. `workflow.world` selects the Workflow world package backing session state, queues, hooks, and streams on the root agent. |
168
+ | `outputSchema` | Standard Schema or a JSON Schema object | none | Structured return type for task-mode runs (a subagent, schedule, or remote job). Interactive conversation turns ignore it unless the client supplies a per-message schema. |
169
+ | `build` | `{ externalDependencies?: string[] }` | none | Hosted-build packaging controls. `externalDependencies` keeps listed packages external while eve compiles authored modules such as tools and channels, and traces those packages into the hosted output. |
153
170
 
154
171
  `externalDependencies` is a packaging control only. It keeps selected packages as runtime dependencies in the hosted output; it does not authorize, configure, or review any third-party service those packages may call.
155
172
 
@@ -0,0 +1,209 @@
1
+ ---
2
+ title: "Chat SDK"
3
+ description: "Bridge any Vercel Chat SDK adapter — Slack, Discord, Telegram, WhatsApp, email, and more — to your agent through one channel, using your own credentials and state store."
4
+ ---
5
+
6
+ The Chat SDK channel connects your agent to any [Vercel Chat SDK](https://chat-sdk.dev) adapter. You pick an adapter (`@chat-adapter/slack`, `@resend/chat-sdk-adapter`, and so on), register handlers for the messages you care about, and call `send` to hand each turn to eve. Use it to reach a surface eve does not ship a first-class channel for, or when you want to manage credentials and state with the Chat SDK's own primitives rather than [Vercel Connect](../guides/auth-and-route-protection). See [Channels](./overview) for the contract this builds on.
7
+
8
+ You supply an adapter and a state store: the adapter owns provider auth, webhook verification, and delivery, while eve owns session dispatch, streaming, typing, and human-in-the-loop. First-class channels such as [Slack](./slack) manage credentials through Vercel Connect instead — reach for whichever fits the surface you are targeting.
9
+
10
+ ## Install
11
+
12
+ Add eve, the Chat SDK core (`chat`), an adapter, and a state adapter. The example below uses the Resend email adapter with the in-memory state store:
13
+
14
+ ```bash
15
+ npm install eve@latest chat @resend/chat-sdk-adapter @chat-adapter/state-memory
16
+ ```
17
+
18
+ Swap in whichever adapter matches your surface — `@chat-adapter/slack`, `@chat-adapter/discord`, `@chat-adapter/telegram`, and so on. Any Chat SDK adapter works.
19
+
20
+ ## Add the channel
21
+
22
+ `chatSdkChannel` returns `{ bot, channel, send }`. Register Chat SDK handlers on `bot`, call `send` from those handlers to start or resume an eve session, and export `channel` as the module default:
23
+
24
+ ```ts title="agent/channels/resend.ts"
25
+ import { createMemoryState } from "@chat-adapter/state-memory";
26
+ import { createResendAdapter } from "@resend/chat-sdk-adapter";
27
+ import type { Message, Thread } from "chat";
28
+ import { chatSdkChannel } from "eve/channels/chat-sdk";
29
+
30
+ export const { bot, channel, send } = chatSdkChannel({
31
+ userName: "Resend Bot",
32
+ adapters: {
33
+ resend: createResendAdapter({
34
+ fromAddress: "hello@example.com",
35
+ fromName: "Resend Bot",
36
+ }),
37
+ },
38
+ state: createMemoryState(),
39
+ streaming: false,
40
+ });
41
+
42
+ bot.onNewMention(async (thread: Thread, message: Message) => {
43
+ await thread.subscribe();
44
+ await send(message.text, { thread });
45
+ });
46
+
47
+ bot.onSubscribedMessage(async (thread: Thread, message: Message) => {
48
+ await send(message.text, { thread });
49
+ });
50
+
51
+ export default channel;
52
+ ```
53
+
54
+ `adapters` is a map of adapter name to adapter instance; each entry mounts its own webhook (see below). `state` takes any Chat SDK state adapter: `createMemoryState()` is fine for local development, but use a durable adapter (Redis, Upstash, etc.) in production so thread subscriptions and inbound deduplication survive restarts. `send` accepts a plain string, an AI SDK `UserContent` array, or a `SendPayload`, and must be called from inside a Chat SDK handler — it dispatches the turn on the webhook that is currently running.
55
+
56
+ Deploy once the channel file is in place:
57
+
58
+ ```bash
59
+ eve deploy
60
+ ```
61
+
62
+ `eve deploy` links the project if needed and deploys to Vercel production.
63
+
64
+ ## Configure the webhook route
65
+
66
+ Each adapter mounts one `POST` route at `/eve/v1/{adapterName}`, so the `resend` adapter above is served at `/eve/v1/resend`. Point your provider's webhook (the Resend inbound address, the Slack Event Subscriptions URL, etc.) at that path.
67
+
68
+ Override the base path for every adapter with `route`, or pin an individual adapter's path with `routes`:
69
+
70
+ ```ts
71
+ export const { bot, channel, send } = chatSdkChannel({
72
+ userName: "Resend Bot",
73
+ adapters: { resend: createResendAdapter({ fromAddress: "hello@example.com" }) },
74
+ state: createMemoryState(),
75
+ route: "/webhooks", // resend now mounts at /webhooks/resend
76
+ routes: { resend: "/webhooks/inbound-email" }, // …or pin it exactly
77
+ });
78
+ ```
79
+
80
+ Use `routes` when a provider requires a fixed URL or when you are migrating an existing endpoint without changing the provider's settings.
81
+
82
+ ## How the channel handles messages
83
+
84
+ ### Dispatch
85
+
86
+ You choose which Chat SDK events start a turn by registering handlers on `bot` and calling `send`:
87
+
88
+ - `bot.onNewMention(thread, message)` fires on a fresh `@mention` (or, for surfaces like email, a new inbound thread). Call `thread.subscribe()` when you want later replies in the same thread to keep reaching the agent.
89
+ - `bot.onSubscribedMessage(thread, message)` fires on subsequent messages in a subscribed thread.
90
+ - `bot.onAction`, `bot.onReaction`, and `bot.onSlashCommand` are available for adapters that emit them.
91
+
92
+ `send(input, options)` starts or resumes the eve session. The `thread` you pass determines the continuation token and the persisted channel state, so replies land back on the originating thread:
93
+
94
+ ```ts
95
+ bot.onNewMention(async (thread, message) => {
96
+ await send(message.text, { thread, title: "Support request" });
97
+ });
98
+ ```
99
+
100
+ `options` accepts `{ thread, auth?, title?, mode?, callback?, adapterName? }`. `title` sets the eve session's display title without changing the model message; `auth` attaches an authenticated principal to the turn.
101
+
102
+ ### Delivery
103
+
104
+ The default handlers post the agent's reply back to the thread — no `events` override required. Completed assistant messages are posted as markdown (`{ markdown: … }`) so adapters render rich text and email HTML rather than a raw string.
105
+
106
+ Streaming is on by default: the channel posts an initial message and edits it as tokens arrive (`message.appended`), throttled by `streamingEditIntervalMs` (default `1000`). Set `streaming: false` for surfaces that deliver one message per turn — email, for example — so the reply posts once on completion instead of editing:
107
+
108
+ ```ts
109
+ chatSdkChannel({
110
+ userName: "Resend Bot",
111
+ adapters: { resend: createResendAdapter({ fromAddress: "hello@example.com" }) },
112
+ state: createMemoryState(),
113
+ streaming: false,
114
+ });
115
+ ```
116
+
117
+ Typing indicators post automatically where the adapter supports them: `Working…` on `turn.started`, and tool status on `actions.requested`.
118
+
119
+ ### Optional capabilities degrade gracefully
120
+
121
+ Adapters do not all implement every operation. When an adapter's `startTyping` or `editMessage` throws a `NotImplementedError` (or an error with code `NOT_IMPLEMENTED`), the channel swallows it: typing indicators are skipped, and a streaming edit falls back to a single final post for the rest of the session. You never have to guard optional capabilities in your own handlers. The same predicate is exported as `isNotImplemented` if you want it in custom `events`:
122
+
123
+ ```ts
124
+ import { isNotImplemented } from "eve/channels/chat-sdk";
125
+ ```
126
+
127
+ Override any default by passing `events`. Handlers receive `(eventData, channel, ctx)`, with the rebuilt Chat SDK thread on `channel.thread`:
128
+
129
+ ```ts
130
+ chatSdkChannel({
131
+ userName: "Resend Bot",
132
+ adapters: { resend: createResendAdapter({ fromAddress: "hello@example.com" }) },
133
+ state: createMemoryState(),
134
+ events: {
135
+ "message.completed"(eventData, channel) {
136
+ if (eventData.finishReason === "tool-calls" || !eventData.message || !channel.thread) return;
137
+ return channel.thread.post({ markdown: eventData.message });
138
+ },
139
+ },
140
+ });
141
+ ```
142
+
143
+ ### Human-in-the-loop (HITL)
144
+
145
+ HITL prompts render as a Chat SDK `Card` with buttons. Button clicks resume the parked session automatically — the channel wires `bot.onAction` for you. Change the action-id prefix with `inputActionPrefix` (default `eve_input:`) if your app already uses it, and provide `resolveInputAuth` to carry user or tenant auth across the resume:
146
+
147
+ ```ts
148
+ chatSdkChannel({
149
+ userName: "Support Bot",
150
+ adapters: { slack: createSlackAdapter() },
151
+ state: createMemoryState(),
152
+ resolveInputAuth: (event) => ({
153
+ authenticator: "slack",
154
+ principalType: "user",
155
+ principalId: event.user?.userId ?? "unknown",
156
+ attributes: {},
157
+ }),
158
+ });
159
+ ```
160
+
161
+ ### Proactive sessions
162
+
163
+ Start a session without an inbound webhook through `channel.receive({ message, target, auth })` — from a schedule `run` handler, or `args.receive(channel, ...)` from another channel. The target is a serialized Chat SDK thread, or `{ threadId, adapterName }` when you only have a provider-native thread id:
164
+
165
+ ```ts
166
+ await channel.receive({
167
+ message: "Your weekly digest is ready.",
168
+ target: { adapterName: "resend", threadId: "resend:user@example.com" },
169
+ auth: null,
170
+ });
171
+ ```
172
+
173
+ ### Attachments
174
+
175
+ `send` takes plain text or an AI SDK `UserContent` array. To forward a Chat SDK message's attachments, convert it with `messageToUserContent`, which returns `message.text` when there are no attachments and a `UserContent` array (text plus one file part per attachment URL) when there are:
176
+
177
+ ```ts
178
+ import { messageToUserContent } from "eve/channels/chat-sdk";
179
+
180
+ bot.onNewMention(async (thread, message) => {
181
+ await send(messageToUserContent(message), { thread });
182
+ });
183
+ ```
184
+
185
+ See [File uploads](./custom#file-uploads) for how eve stages remote file URLs before the model call.
186
+
187
+ ## Configuration reference
188
+
189
+ | Option | Default | Purpose |
190
+ | ------------------------- | ------------ | ------------------------------------------------------------------------ |
191
+ | `adapters` | — | Map of adapter name to Chat SDK adapter instance. One webhook per entry. |
192
+ | `state` | — | Chat SDK state adapter for subscriptions, locks, and dedupe. |
193
+ | `userName` | — | Display name for the bot (a standard Chat SDK `ChatConfig` field). |
194
+ | `route` | `/eve/v1` | Base path for generated adapter webhooks (`{route}/{adapter}`). |
195
+ | `routes` | — | Per-adapter path overrides for fixed or migrated webhook URLs. |
196
+ | `streaming` | `true` | Post-then-edit streaming. Set `false` for one-message-per-turn surfaces. |
197
+ | `streamingEditIntervalMs` | `1000` | Minimum interval between streaming edits. |
198
+ | `events` | built-in | Per-event handlers. A supplied handler replaces that built-in default. |
199
+ | `inputActionPrefix` | `eve_input:` | Prefix for default HITL button action ids. |
200
+ | `resolveInputAuth` | `null` | Auth resolver applied when a HITL button click resumes a session. |
201
+ | `webhook` | — | Extra Chat SDK webhook options (eve owns `waitUntil`). |
202
+
203
+ Any other Chat SDK `ChatConfig` field (for example `concurrency`) is accepted and passed through.
204
+
205
+ ## What to read next
206
+
207
+ - [Channels overview](./overview): the channel contract and every built-in channel
208
+ - [Custom channels](./custom): build a channel for any surface with `defineChannel`
209
+ - [Auth & route protection](../guides/auth-and-route-protection): authenticating inbound traffic
@@ -10,6 +10,7 @@
10
10
  "twilio",
11
11
  "github",
12
12
  "linear",
13
+ "chat-sdk",
13
14
  "custom"
14
15
  ]
15
16
  }
@@ -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