eve 0.10.0 → 0.11.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 (98) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +14 -0
  3. package/dist/src/cli/banner.d.ts +6 -3
  4. package/dist/src/cli/banner.js +1 -1
  5. package/dist/src/cli/commands/init.js +1 -1
  6. package/dist/src/cli/dev/tui/agent-header.js +1 -1
  7. package/dist/src/cli/run.js +1 -1
  8. package/dist/src/evals/runner/run-evals.d.ts +1 -1
  9. package/dist/src/execution/sandbox/bindings/docker.js +1 -1
  10. package/dist/src/execution/sandbox/bindings/microsandbox-lifecycle.js +1 -1
  11. package/dist/src/execution/sandbox/bindings/microsandbox-runtime.d.ts +2 -1
  12. package/dist/src/execution/sandbox/bindings/microsandbox-runtime.js +1 -1
  13. package/dist/src/execution/sandbox/bindings/vercel-errors.d.ts +1 -0
  14. package/dist/src/execution/sandbox/bindings/vercel-errors.js +1 -2
  15. package/dist/src/execution/sandbox/bindings/vercel.d.ts +0 -5
  16. package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
  17. package/dist/src/harness/input-requests.d.ts +20 -1
  18. package/dist/src/harness/input-requests.js +1 -1
  19. package/dist/src/harness/tool-loop.js +1 -1
  20. package/dist/src/internal/application/package.js +1 -1
  21. package/dist/src/protocol/message.d.ts +11 -2
  22. package/dist/src/protocol/message.js +2 -2
  23. package/dist/src/public/next/index.d.ts +1 -7
  24. package/dist/src/public/next/index.js +1 -1
  25. package/dist/src/public/next/vercel-output-config.js +1 -1
  26. package/dist/src/setup/scaffold/create/project.js +1 -1
  27. package/dist/src/setup/scaffold/create/web-template.d.ts +1 -1
  28. package/dist/src/setup/scaffold/create/web-template.js +27 -4
  29. package/dist/src/setup/scaffold/update/channels.js +1 -1
  30. package/docs/README.md +19 -5
  31. package/docs/agent-config.md +16 -19
  32. package/docs/channels/custom.mdx +24 -18
  33. package/docs/channels/discord.mdx +25 -13
  34. package/docs/channels/eve.mdx +24 -6
  35. package/docs/channels/github.mdx +41 -10
  36. package/docs/channels/linear.mdx +29 -36
  37. package/docs/channels/overview.mdx +16 -4
  38. package/docs/channels/slack.mdx +59 -32
  39. package/docs/channels/teams.mdx +19 -7
  40. package/docs/channels/telegram.mdx +23 -9
  41. package/docs/channels/twilio.mdx +28 -6
  42. package/docs/concepts/context-control.md +24 -41
  43. package/docs/concepts/default-harness.md +19 -9
  44. package/docs/concepts/execution-model-and-durability.md +14 -14
  45. package/docs/concepts/security-model.md +32 -8
  46. package/docs/concepts/sessions-runs-and-streaming.md +11 -9
  47. package/docs/connections.mdx +49 -29
  48. package/docs/evals/assertions.mdx +30 -29
  49. package/docs/evals/cases.mdx +10 -10
  50. package/docs/evals/judge.mdx +14 -14
  51. package/docs/evals/overview.mdx +15 -17
  52. package/docs/evals/reporters.mdx +19 -7
  53. package/docs/evals/running.mdx +2 -2
  54. package/docs/evals/targets.mdx +15 -4
  55. package/docs/getting-started.mdx +72 -31
  56. package/docs/guides/auth-and-route-protection.md +18 -12
  57. package/docs/guides/client/continuations.mdx +5 -13
  58. package/docs/guides/client/messages.mdx +2 -2
  59. package/docs/guides/client/output-schema.mdx +2 -2
  60. package/docs/guides/client/overview.mdx +4 -4
  61. package/docs/guides/client/streaming.mdx +6 -5
  62. package/docs/guides/deployment.md +22 -20
  63. package/docs/guides/dev-tui.md +85 -13
  64. package/docs/guides/dynamic-capabilities.md +24 -8
  65. package/docs/guides/dynamic-workflows.md +33 -12
  66. package/docs/guides/frontend/nextjs.mdx +28 -14
  67. package/docs/guides/frontend/nuxt.mdx +21 -4
  68. package/docs/guides/frontend/overview.mdx +11 -11
  69. package/docs/guides/frontend/sveltekit.mdx +20 -3
  70. package/docs/guides/frontend/use-eve-agent-svelte.mdx +106 -14
  71. package/docs/guides/frontend/use-eve-agent-vue.mdx +108 -15
  72. package/docs/guides/hooks.md +14 -60
  73. package/docs/guides/instrumentation.md +24 -18
  74. package/docs/guides/remote-agents.md +19 -15
  75. package/docs/guides/session-context.md +12 -12
  76. package/docs/guides/state.md +25 -9
  77. package/docs/instructions.mdx +18 -10
  78. package/docs/{introduction.md → introduction.mdx} +14 -12
  79. package/docs/reference/cli.md +99 -53
  80. package/docs/reference/meta.json +1 -1
  81. package/docs/reference/project-layout.md +39 -32
  82. package/docs/reference/typescript-api.md +1 -1
  83. package/docs/responsible-use.md +14 -0
  84. package/docs/sandbox.mdx +25 -19
  85. package/docs/schedules.mdx +16 -14
  86. package/docs/skills.mdx +8 -6
  87. package/docs/subagents.mdx +39 -13
  88. package/docs/tools.mdx +13 -9
  89. package/docs/tutorial/connect-a-warehouse.mdx +16 -7
  90. package/docs/tutorial/first-agent.mdx +21 -11
  91. package/docs/tutorial/guard-the-spend.mdx +11 -9
  92. package/docs/tutorial/how-it-runs.mdx +10 -8
  93. package/docs/tutorial/query-sample-data.mdx +8 -8
  94. package/docs/tutorial/remember-definitions.mdx +5 -5
  95. package/docs/tutorial/run-analysis.mdx +13 -11
  96. package/docs/tutorial/ship-it.mdx +70 -14
  97. package/docs/tutorial/team-playbooks.mdx +33 -10
  98. package/package.json +1 -1
@@ -1,44 +1,116 @@
1
1
  ---
2
2
  title: "Dev TUI"
3
- description: "Drive an Eve agent locally in an interactive terminal UI: chat, stream, approve tools, answer questions, tune the display, and point it at a deployment."
3
+ description: "Drive an Eve agent locally in an interactive terminal UI. Chat, stream, approve tools, answer questions, tune the display, and point it at a deployment."
4
4
  ---
5
5
 
6
- `eve dev` boots the local runtime and drops you into an interactive terminal UI. You chat with the agent, watch it stream, approve its tool calls, and answer the questions it asks back:
6
+ `eve dev` boots the local runtime and drops you into an interactive terminal UI. You chat with the agent, watch it stream, approve its tool calls, and answer the questions it asks back.
7
7
 
8
8
  ```bash
9
9
  eve dev
10
10
  ```
11
11
 
12
- On startup the TUI prints a brand line with your agent's name, plus a rotating tip (local sessions only):
12
+ On startup the TUI prints a brand line with your agent's name, plus a rotating tip (local sessions only).
13
13
 
14
14
  ```text
15
15
  eve weather-agent
16
16
  Use /channels to add more ways to reach your agent.
17
17
  ```
18
18
 
19
- If agent discovery reported problems, an error/warning count renders between the two lines. Instructions, tools, skills, and subagents are one `eve info` away, and `/help` lists every command.
19
+ If agent discovery reported problems, an error and warning count renders between the two lines. Instructions, tools, skills, and subagents are one `eve info` away, and `/help` lists every command. The TUI also runs a startup check. A missing model-provider setup surfaces as an attention line (`⚠ 1 setup issue: model provider not linked · /model`) so the fix is visible before the first message fails, with each command's outcome hanging under it on a `⎿` connector.
20
20
 
21
- From there the conversation streams straight into your terminal's normal scrollback — your prompts, the agent's replies, reasoning, tool calls, nested subagents, connection-authorization prompts, and any captured `stdout`, `stderr`, or sandbox lifecycle lines — so you keep native scrolling, copy/paste, and a transcript that persists after you exit. Each turn is rendered without boxes: a colored gutter glyph marks who's speaking, tool calls collapse to a one-line summary (`✓ get_weather city="SF" → 73°F`), and a subagent's work is indented beneath its `◆` header. A sticky footer keeps you oriented. When input is ready, the prompt stays bare until you type; while a turn or setup action owns the terminal, only its live status is shown. Beneath the prompt or status, a persistent line shows the model, the session's token flow (`↑ 394.4K ↓ 4.3K`), the linked Vercel project and team (`▲ my-agent (acme)`), and a yellow `/deploy pending` marker once a channel added this session still needs `/deploy`. The Vercel segment stays hidden until the directory is linked. Press `Enter` to send; `Ctrl+C` interrupts a running turn or quits at the prompt. Slash commands: `/new` starts a fresh session and `/exit` quits.
21
+ ## Reading the transcript
22
22
 
23
- When `eve dev` runs the server locally, five more slash commands manage the project without leaving the session. `/vc` installs the Vercel CLI (a global install with your package manager) when it is missing — the fix command the "Vercel CLI not found" diagnostic points at. `/login` signs in to Vercel through the CLI's browser flow: the panel waits while you authenticate in the browser and Cancel stops waiting. These are the prerequisites the others route to — a logged-out `/model` link, `/channels` Slack provisioning, and `/deploy` all point you at `/login` (or `/vc` when the CLI itself is absent) instead of failing with a raw error, and a `403` from a team that enforces SSO routes to `/login` too (re-authenticating completes the team's SSO). Bare `/model` opens a configure menu that loops until Done (or Esc). "Change model" runs the same searchable model picker setup uses (the AI Gateway catalog, pre-selected on the model the runtime is serving); a model change is written into your agent's authored source, and the command reports success only after Eve confirms the new id (`/model <provider/model-id>` applies one directly, skipping the menu). The provider row opens the provider questions: which model provider to use (picking something other than AI Gateway shows wiring instructions for your own provider and stops there, leaving any existing setup untouched) and how to connect to AI Gateway — paste your own `AI_GATEWAY_API_KEY`, saved straight to `.env.local`, or connect via a project, which asks for a Vercel team and then opens that team's existing-project list (picking again re-links) before pulling the project's environment so an AI Gateway credential lands in `.env.local`; the dev server reloads env files automatically, no restart needed. The row demands attention (a bold yellow "Configure provider" with "Required to enable the agent") until a link or gateway credential is detected, then names the connection (e.g. "AI Gateway (Linked to my-project in my-team)") after, and each action's latest outcome stays visible beneath the menu (e.g. "✓ Model changed to openai/gpt-5.5"). `/channels` shows the agent's channel list — already-registered channels render as checked, focusable rows with an "Already installed" hint — and adds the one you pick, including the Slack Connect provisioning, then installs the dependencies the scaffold added so the dev server can load the new channels right away; after each addition the list repaints with the channel checked, until Done (or Esc) leaves the flow. `/deploy` ships the agent to Vercel production, linking first when the directory is unlinked. Each command echoes as an invocation line, asks through a bordered panel that takes the input area's place — one question at a time, clearly separate from the chat transcript — and finishes with a one-line `⎿` result; loading states stay on the ephemeral status line instead of piling into the transcript. These commands are not available when connected to a remote server with `--url`, and when a turn fails because AI Gateway authentication is missing or stale, the error points you at `/model` directly. The TUI also checks at startup: a missing model-provider setup surfaces as an attention line — `⚠ 1 setup issue: model provider not linked · /model` — so the fix is visible before the first message fails, and a logged-out Vercel session surfaces the same way as `⚠ 1 setup issue: not logged in · /login` (or `Vercel CLI not found · /vc` when the CLI itself is absent). Each command's outcome hangs under it with the `⎿` connector.
23
+ The conversation streams straight into your terminal's normal scrollback, so you keep native scrolling, copy and paste, and a transcript that persists after you exit. The scrollback holds your prompts, the agent's replies, reasoning, tool calls, nested subagents, connection-authorization prompts, and any captured `stdout`, `stderr`, or sandbox lifecycle lines.
24
24
 
25
- In the AI Gateway connection picker, "Connect via a project" is disabled when the Vercel CLI is missing, the CLI session is logged out, or Vercel cannot be reached. The disabled reason points to `/vc`, `/login`, or the network problem, while "Use my own key" remains available.
25
+ Each turn renders without boxes. A colored gutter glyph marks who is speaking, tool calls collapse to a one-line summary (`✓ get_weather city="SF" 73°F`), and a subagent's work is indented beneath its `◆` header. When input is ready, the prompt stays bare until you type. While a turn or setup action owns the terminal, only its live status shows.
26
26
 
27
- The prompt input behaves like a shell line editor: `↑`/`↓` cycle through the messages you've sent this session, `←`/`→`, Home/End, and `Ctrl+A`/`Ctrl+E` move the caret, and `Ctrl+U`/`Ctrl+K`/`Ctrl+W` kill the line, the rest of the line, or the previous word. If a turn fails terminally — the server session dies or the connection drops — the TUI starts a fresh session and notes it inline so you can keep going (server-side context resets with the old session). Errors render compactly, with docs links highlighted, and a code bug escaping your agent's own code shows its stack trace dim beneath the error headline. Captured server `stdout`/`stderr` renders as dim, indented log runs behind a `│` rule — consecutive lines from the same source share one label while sandbox lifecycle lines use their own label. Dev-server rebuilds condense further, into one status row that updates in place: `tui/setup-panel.ts changed · rebuilding…`, then `· rebuilt`. Only the latest rebuild shows, and paths shrink to their last two components. By default, `eve dev` shows `stderr` and keeps stdout and sandbox lines buffered but hidden. `/loglevel <all|stderr|sandbox|none>` switches what the transcript shows retroactively, and `--logs` sets the starting mode. Bare `/loglevel` reports the current mode. At the idle prompt, `Ctrl+L` cycles `none → all → stderr → sandbox → none` and briefly shows the selected mode in the status line; `Ctrl+R` redraws.
27
+ A persistent line beneath the prompt or status shows the model, the session's token flow (`↑ 394.4K 4.3K`), the linked Vercel project and team (`▲ my-agent (acme)`), and a yellow `/deploy pending` marker once a channel added this session still needs `/deploy`. The Vercel segment stays hidden until the directory is linked.
28
28
 
29
- The agent will sometimes need something from you, and the TUI asks inline. Tool approvals are a `y`/`n`. Option questions let you pick with `↑`/`↓` and `Enter`, or you can type a freeform answer. If a tool needs an authorized [connection](../connections), the URL shows up right in the transcript, and the turn picks back up once you've finished the flow.
29
+ Errors render compactly with docs links highlighted. A code bug escaping your agent's own code shows its stack trace dim beneath the error headline. Dev-server rebuilds condense into one status row that updates in place (`tui/setup-panel.ts changed · rebuilding…`, then rebuilt`); only the latest rebuild shows, and paths shrink to their last two components.
30
30
 
31
- Density flags accept `full` / `collapsed` / `auto-collapsed` / `hidden`:
31
+ ## Slash commands
32
+
33
+ Each command echoes as an invocation line, asks through a bordered panel that takes the input area's place (one question at a time, separate from the chat transcript), and finishes with a one-line `⎿` result. Loading states stay on the ephemeral status line instead of piling into the transcript.
34
+
35
+ | Command | Does |
36
+ | ----------- | --------------------------------------------------------------------------------------------------------------------------------- |
37
+ | `/model` | Opens a configure menu that loops until Done (or Esc). See [Configure the model and provider](#configure-the-model-and-provider). |
38
+ | `/channels` | Shows the agent's channel list and adds the one you pick. See [Add a channel](#add-a-channel). |
39
+ | `/deploy` | Ships the agent to Vercel production, linking the directory first when it is unlinked. |
40
+ | `/loglevel` | Switches which logs the transcript shows. See [Control what logs show](#control-what-logs-show). |
41
+ | `/new` | Starts a fresh session. |
42
+ | `/exit` | Quits the TUI. |
43
+ | `/help` | Lists every command. |
44
+
45
+ `/model`, `/channels`, and `/deploy` manage the project and are available only when `eve dev` runs the server locally, not when connected to a remote server with `--url`.
46
+
47
+ ### Configure the model and provider
48
+
49
+ Bare `/model` opens the configure menu. "Change model" runs the same searchable model picker setup uses (the Vercel AI Gateway catalog, pre-selected on the model the runtime is serving). A model change is written into your agent's authored source, and the command reports success only after Eve confirms the new id. `/model <provider/model-id>` applies one directly, skipping the menu.
50
+
51
+ The provider row opens the provider questions: which model provider to use, and how to connect. Picking something other than Vercel AI Gateway shows wiring instructions for your own provider and stops there, leaving any existing setup untouched. For Vercel AI Gateway, you either paste your own `AI_GATEWAY_API_KEY` (saved straight to `.env.local`) or connect via a project. Connecting via a project asks for a Vercel team, opens that team's existing-project list (picking again re-links), then pulls the project's environment so an AI Gateway credential lands in `.env.local`. The dev server reloads env files automatically, with no restart needed.
52
+
53
+ The provider row demands attention (a bold yellow "Configure provider" with "Required to enable the agent") until a link or gateway credential is detected, then names the connection afterward (for example "AI Gateway (Linked to my-project in my-team)"). Each action's latest outcome stays visible beneath the menu (for example "✓ Model changed to openai/gpt-5.5"). When a turn fails because AI Gateway authentication is missing or stale, the error points you at `/model` directly.
54
+
55
+ ### Add a channel
56
+
57
+ `/channels` shows the agent's channel list. Already-registered channels render as checked, focusable rows with an "Already installed" hint. Picking one adds it (including the Slack Connect provisioning), then installs the dependencies the scaffold added so the dev server can load the new channels right away. After each addition the list repaints with the channel checked, until Done (or Esc) leaves the flow.
58
+
59
+ ## Keyboard shortcuts
60
+
61
+ The prompt input behaves like a shell line editor.
62
+
63
+ | Key | Action |
64
+ | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
65
+ | `Enter` | Send the message. |
66
+ | `Ctrl+C` | Interrupt a running turn, or quit at the prompt. |
67
+ | `↑` / `↓` | Cycle through the messages you have sent this session. |
68
+ | `←` / `→`, `Home` / `End`, `Ctrl+A` / `Ctrl+E` | Move the caret. |
69
+ | `Ctrl+U` / `Ctrl+K` / `Ctrl+W` | Kill the whole line, the rest of the line, or the previous word. |
70
+ | `Ctrl+L` | Cycle the log display mode (`none → all → stderr → sandbox → none`) and briefly show the mode in the status line. |
71
+ | `Ctrl+R` | Redraw the screen. |
72
+
73
+ If a turn fails terminally (the server session dies or the connection drops), the TUI starts a fresh session and notes it inline so you can keep going. Server-side context resets with the old session.
74
+
75
+ ## Answer the agent inline
76
+
77
+ When the agent needs something from you, the TUI asks inline.
78
+
79
+ - Tool approvals are a `y` or `n`.
80
+ - Option questions let you pick with `↑` / `↓` and `Enter`, or you can type a freeform answer.
81
+ - If a tool needs an authorized [connection](../connections), the URL shows up right in the transcript, and the turn picks back up once you finish the flow.
82
+
83
+ ## Control what logs show
84
+
85
+ By default, `eve dev` shows `stderr` and keeps stdout and sandbox lines buffered but hidden. Captured server `stdout` and `stderr` render as dim, indented log runs behind a `│` rule (consecutive lines from the same source share one label), while sandbox lifecycle lines use their own label.
86
+
87
+ - `/loglevel <all|stderr|sandbox|none>` switches what the transcript shows, retroactively. Bare `/loglevel` reports the current mode.
88
+ - `--logs <all|stderr|sandbox|none>` sets the starting mode at launch (default `stderr`).
89
+ - `Ctrl+L` at the idle prompt cycles `none → all → stderr → sandbox → none`.
90
+
91
+ ## Display flags
92
+
93
+ Density flags control how much of each section renders. They accept `full`, `collapsed`, `auto-collapsed`, or `hidden`.
32
94
 
33
95
  ```bash
34
96
  eve dev --tools full --assistant-response-stats tokens --context-size 200000
35
97
  ```
36
98
 
37
- Other useful flags: `--subagents`, `--reasoning`, `--logs <all|stderr|sandbox|none>`, `--host`/`--port`, and `--no-ui` (headless, also the automatic fallback when stdout isn't a TTY).
99
+ | Flag | Values | Effect |
100
+ | ----------------------------------- | -------------------------------------------------- | ------------------------------------------------------- |
101
+ | `--tools <mode>` | `full` / `collapsed` / `auto-collapsed` / `hidden` | How tool calls render (default `auto-collapsed`). |
102
+ | `--reasoning <mode>` | `full` / `collapsed` / `auto-collapsed` / `hidden` | How reasoning renders (default `full`). |
103
+ | `--subagents <mode>` | `full` / `collapsed` / `auto-collapsed` / `hidden` | How subagent sections render. |
104
+ | `--connection-auth <mode>` | `full` / `collapsed` / `auto-collapsed` / `hidden` | How connection authorization renders. |
105
+ | `--assistant-response-stats <mode>` | `tokens` / `tokensPerSecond` | Which statistic the assistant header shows. |
106
+ | `--context-size <tokens>` | a token count | Model context window size, shown as a usage percentage. |
107
+ | `--logs <mode>` | `all` / `stderr` / `sandbox` / `none` | Which server and agent logs to show (default `stderr`). |
108
+
109
+ Connection flags: `--host` and `--port` bind the local server, and `--no-ui` runs headless (also the automatic fallback when stdout is not a TTY). See the [CLI](../reference/cli) for the full flag list.
38
110
 
39
111
  ## Remote: `eve dev <url>`
40
112
 
41
- Pass a URL and the TUI talks to a running deployment instead of spinning up a local server. That's handy for a Vercel preview or your production app:
113
+ Pass a URL and the TUI talks to a running deployment instead of starting a local server, which is handy for a Vercel preview or your production app.
42
114
 
43
115
  ```bash
44
116
  eve dev https://<your-app>
@@ -48,5 +120,5 @@ The bare URL is shorthand for `--url`. `--host`, `--port`, and `--no-ui` are ign
48
120
 
49
121
  ## What to read next
50
122
 
51
- - [instrumentation.ts](./instrumentation): OpenTelemetry, hooks, and the error catalog.
123
+ - [Observability](./instrumentation): OpenTelemetry, run tags, and common failures.
52
124
  - [CLI](../reference/cli): every command and flag.
@@ -3,13 +3,13 @@ title: "Dynamic Capabilities"
3
3
  description: "Resolve tools, skills, and instructions at runtime with defineDynamic: the resolver events, execution order, and how dynamic tools survive step boundaries."
4
4
  ---
5
5
 
6
- Sometimes you can't name a tool until the session starts. `defineDynamic` resolves capabilities from a session event at runtime rather than declaring them up front, which is what you want when the right tools, skills, or instructions hinge on who the caller is, what tenant they belong to, feature flags, or external data. The [tools](../tools), [skills](../skills), and [instructions](../instructions) guides each point here for their dynamic form.
6
+ `defineDynamic` resolves tools, skills, and instructions at runtime from a session event instead of declaring them up front. Reach for it when the right capabilities aren't known until the session starts, because they hinge on who the caller is, what tenant they belong to, feature flags, or external data. The [tools](../tools), [skills](../skills), and [instructions](../instructions) guides each point here for their dynamic form.
7
7
 
8
8
  ## Dynamic tools
9
9
 
10
10
  Pass `defineDynamic` an `events` object whose handlers return either a single `defineTool(...)`, a `Record<string, defineTool(...)>`, or `null` for no tools. Wrap every entry in `defineTool()`. The wrapper stamps them so their `execute` functions survive workflow step boundaries.
11
11
 
12
- The example below builds one tool per warehouse table. A map return names tools `slug__key`, so the model sees `query__orders`, `query__users`, and so on:
12
+ The example below builds one tool per warehouse table. A map return names tools `slug__key`, so the model sees `query__orders`, `query__users`, and so on.
13
13
 
14
14
  ```ts title="agent/tools/query.ts"
15
15
  import { defineDynamic, defineTool } from "eve/tools";
@@ -33,6 +33,10 @@ export default defineDynamic({
33
33
  });
34
34
  ```
35
35
 
36
+ ### `execute` must be an inline function
37
+
38
+ Write `execute` as an inline function expression, arrow, or method shorthand placed directly as the property value. The bundler transform does not detect `execute: myFn` or `execute: makeFn()`, so those tools work on the first step but do not survive replay (re-running a step after a crash or resume; see [Execution model & durability](../concepts/execution-model-and-durability)). On later steps the transform reconstructs each `execute` from its stored closure variables instead of re-running the resolver, which is why it has to be inline.
39
+
36
40
  ### Naming
37
41
 
38
42
  | Return shape | File | Tool name(s) |
@@ -51,33 +55,45 @@ A single return produces one tool named after the file slug, identical to a stat
51
55
  | `turn.started` | Once per turn | Every model call in the turn |
52
56
  | `step.started` | Before each model call | That model call |
53
57
 
54
- **Limitation.** `execute` must be an inline function (function expression, arrow, or method shorthand written directly as the property value). `execute: myFn` or `execute: makeFn()` is not detected by the transform, so the tool works on the first step but won't survive replay.
55
-
56
58
  ### Execution order
57
59
 
58
- When a stream event fires, three things happen in order: the channel adapter handler runs and the event is written to the durable stream, then stream-event [hooks](./hooks) fire, then dynamic tool resolvers subscribed to that event run and update the tool set. The tool loop reads the current set right before each model call, so a mid-turn update is visible on the next call.
60
+ When a stream event fires, three things happen in order.
61
+
62
+ 1. The channel adapter handler runs and the event is written to the durable stream.
63
+ 2. Stream-event [hooks](./hooks) fire.
64
+ 3. Dynamic tool resolvers subscribed to that event run and update the tool set.
65
+
66
+ The tool loop reads the current set right before each model call, so a mid-turn update is visible on the next call.
59
67
 
60
68
  A single file can declare handlers for several events, and the most recently fired one owns that file's tool set. Re-resolve on `turn.started` to replace what `session.started` returned:
61
69
 
62
70
  ```ts title="agent/tools/catalog.ts"
71
+ import { defineDynamic, defineTool } from "eve/tools";
72
+ import { z } from "zod";
73
+ import { runReadOnly, searchCatalog } from "../lib/catalog.js";
74
+
63
75
  export default defineDynamic({
64
76
  events: {
65
77
  "session.started": async (_event, ctx) => ({
66
78
  query: defineTool({
67
- /* ... */
79
+ description: "Run a read-only query.",
80
+ inputSchema: z.object({ sql: z.string() }),
81
+ execute: ({ sql }) => runReadOnly(sql),
68
82
  }),
69
83
  }),
70
84
  // On each turn, re-resolve. Replaces this file's session.started tools for later calls.
71
85
  "turn.started": async (_event, ctx) => ({
72
86
  search: defineTool({
73
- /* ... */
87
+ description: "Search the catalog.",
88
+ inputSchema: z.object({ term: z.string() }),
89
+ execute: ({ term }) => searchCatalog(term),
74
90
  }),
75
91
  }),
76
92
  },
77
93
  });
78
94
  ```
79
95
 
80
- Resolvers across files run concurrently. On later steps the bundler transform reconstructs each `execute` from its stored closure variables instead of re-running the resolver, which is why `execute` has to be inline.
96
+ Resolvers across files run concurrently.
81
97
 
82
98
  ## Dynamic skills
83
99
 
@@ -3,11 +3,11 @@ title: "Dynamic Workflows"
3
3
  description: "The experimental Workflow tool: let the model orchestrate its own subagents from model-authored JavaScript as one durable step."
4
4
  ---
5
5
 
6
- The experimental `Workflow` tool lets the model write JavaScript that coordinates the agent's own subagents as a single durable step: running them in sequence, feeding one result into the next, fanning out over a list, and combining the results. You flip on the capability; the model decides and runs the orchestration. Think of it as the agents-only slice of code mode.
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. It is the agents-only slice of [code mode](../agent-config#other-defineagent-fields) (the broader `codeMode` flag that routes all of an agent's tools through model-authored JavaScript).
7
7
 
8
- A single turn can already call several subagents, and parallel tool calls dispatch concurrently. What a workflow adds is _programmatic_ coordination: how many subagents to run based on an earlier result, which output feeds which call, and how to combine everything. That's logic the model can't express as a few one-off calls.
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
9
 
10
- ## Enable it
10
+ ## Enable the Workflow tool
11
11
 
12
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
13
 
@@ -26,27 +26,48 @@ export default defineAgent({
26
26
  });
27
27
  ```
28
28
 
29
- Ask for a "weekly business review": the model map-reduces `analyst` over the metrics it picks (width decided at runtime) and resumes if a child parks for approval.
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
30
 
31
- ## What it can orchestrate
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
32
51
 
33
- 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's the whole list. No files, network, shell, skills, or connections. It's 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.
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.
34
53
 
35
54
  ## Where the JavaScript runs
36
55
 
37
- 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: no `process`, no `globalThis` from the agent, no `import`/`require`. The program can reach exactly two things, the agent functions bridged in as `tools.<name>` and the ordinary language built-ins.
56
+ 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.
38
57
 
39
- That's an allowlist, not a denylist. The sandbox can't read files, open a socket, or see an environment variable because those simply aren't 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 just like a direct delegation. The orchestration glue stays inside the sandbox.
58
+ 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.
40
59
 
41
- ## How it behaves
60
+ ## Durability, approvals, and observability
42
61
 
43
- - **Durable.** The whole orchestration counts as one step. Subagents dispatched together run concurrently, and if a run parks on a long-running or human-gated child, it resumes where it left off after a restart.
44
- - **HITL-safe.** A subagent that needs approval mid-run surfaces its request to the user, and the workflow picks back up once that's answered, same as direct delegation.
62
+ - **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.
63
+ - **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.
45
64
  - **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.
46
65
 
47
66
  ## Relationship to code mode
48
67
 
49
- Code mode is the broader version: the model drives _all_ of an agent's tools (files, shell, web, and agents) from JavaScript. A workflow carves out the agents-only slice, just the subagents. The two don't interfere. Enabling the `Workflow` tool leaves code mode untouched, and an agent can run both at once.
68
+ [Code mode](../agent-config#other-defineagent-fields) is the broader version, where the model drives _all_ of an agent's tools (files, shell, web, and agents) from JavaScript. A workflow covers only the subagents. The two do not interfere. Enabling the `Workflow` tool leaves code mode untouched, and an agent can run both at once.
69
+
70
+ `codeMode` is experimental and may change or be removed.
50
71
 
51
72
  ## What to read next
52
73
 
@@ -3,7 +3,13 @@ title: "Next.js"
3
3
  description: "Run an Eve agent and a Next.js app as one project with withEve."
4
4
  ---
5
5
 
6
- `eve/next` lets you ship a Next.js frontend and an Eve agent as a single project. Wrap your config with `withEve()` and the two run together: one dev server, one Vercel deploy. [`useEveAgent`](./overview) finds the mounted routes on its own, so there's no CORS to fight and no URL env vars to keep in sync.
6
+ `eve/next` ships a Next.js frontend and an Eve agent as a single project. Wrap your config with `withEve()` to run both from one dev server and one Vercel deploy. [`useEveAgent`](./overview) finds the mounted routes on its own, so there's no CORS to configure and no URL env vars to keep in sync.
7
+
8
+ ## Prerequisites
9
+
10
+ - The `eve` package installed in your project (`npm install eve@latest`).
11
+ - An existing Eve agent directory. If you don't have one, start from [Getting started](../../getting-started).
12
+ - A Next.js app to mount the agent in.
7
13
 
8
14
  ## Wrap the Next.js config
9
15
 
@@ -16,7 +22,7 @@ const nextConfig: NextConfig = {};
16
22
  export default withEve(nextConfig);
17
23
  ```
18
24
 
19
- By default `withEve()` looks for an `agent/` folder next to your Next.js project root. If the agent lives somewhere else, point at it with `eveRoot`:
25
+ By default `withEve()` looks for an `agent/` folder inside your Next.js project root. If the agent lives somewhere else, point at it with `eveRoot`:
20
26
 
21
27
  ```ts
22
28
  export default withEve(nextConfig, {
@@ -28,15 +34,14 @@ export default withEve(nextConfig, {
28
34
 
29
35
  All fields are optional.
30
36
 
31
- | Option | Type | Default | Purpose |
32
- | ----------------------- | --------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
33
- | `eveRoot` | `string` | Next.js app root | Path to the Eve app root, relative to `process.cwd()` unless absolute. Set it when the agent lives outside the Next.js project. |
34
- | `eveBuildCommand` | `string` | `"eve build"` | Build command for the generated Eve Vercel service. Use it when the Eve service needs project-specific prework, without changing the Next.js build. |
35
- | `configureVercelOutput` | `boolean` | `true` | Set to `false` to skip creating or updating `.vercel/output/config.json`. By default `withEve` writes the `experimentalServices` entries for both apps. |
36
- | `servicePrefix` | `string` | `"/_eve_internal/eve"` | Private Vercel route namespace for the Eve service. Must match the Eve service's mount in your Vercel Build Output config when you set it manually. |
37
- | `devServerTimeoutMs` | `number` | `180000` | Maximum time to wait for the Eve development server to become available. |
37
+ | Option | Type | Default | Purpose |
38
+ | -------------------- | -------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
39
+ | `eveRoot` | `string` | Next.js app root | Path to the Eve app root, relative to `process.cwd()` unless absolute. Set it when the agent lives outside the Next.js project. |
40
+ | `eveBuildCommand` | `string` | `"eve build"` | Build command for the generated Eve Vercel service. Use it when the Eve service needs project-specific prework, without changing the Next.js build. |
41
+ | `servicePrefix` | `string` | `"/_eve_internal/eve"` | Private Vercel route namespace for the Eve service. Must match the Eve service's mount in your Vercel Build Output config when you set it manually. |
42
+ | `devServerTimeoutMs` | `number` | `180000` | Maximum time to wait for the Eve development server to become available. |
38
43
 
39
- For unusually slow cold starts, increase the development timeout:
44
+ For slow cold starts, increase the development timeout:
40
45
 
41
46
  ```ts
42
47
  export default withEve(nextConfig, {
@@ -46,7 +51,7 @@ export default withEve(nextConfig, {
46
51
 
47
52
  ## Call the hook
48
53
 
49
- With `withEve()` in `next.config.ts`, the Eve routes are same-origin, so client code can call [`useEveAgent`](./overview) without naming a host. Cookie-based auth just works, whether that's Auth.js or any session cookie, since the browser already sends those cookies on every Eve request. For non-cookie schemes, attach the credentials yourself:
54
+ With `withEve()` in `next.config.ts`, the Eve routes are same-origin, so client code can call [`useEveAgent`](./overview) without naming a host. Cookie-based auth (Auth.js or any session cookie) needs no extra wiring, since the browser already sends those cookies on every Eve request. For non-cookie schemes, attach the credentials yourself:
50
55
 
51
56
  ```tsx
52
57
  const agent = useEveAgent({
@@ -56,7 +61,16 @@ const agent = useEveAgent({
56
61
  });
57
62
  ```
58
63
 
59
- Before deploying a user-facing app, add `agent/channels/eve.ts` so production requests run your app's auth policy. See [Channels](../../channels/overview) and [Auth & route protection](../auth-and-route-protection).
64
+ The default Eve channel is fail-closed. With no `agent/channels/eve.ts` authored, Eve registers `eveChannel({ auth: [localDev(), vercelOidc()] })`: `localDev()` opens the routes on localhost, `vercelOidc()` admits Vercel OIDC callers in production, and everything else gets a `401`. To run your app's own auth policy, add `agent/channels/eve.ts`:
65
+
66
+ ```ts title="agent/channels/eve.ts"
67
+ import { eveChannel } from "eve/channels/eve";
68
+ import { localDev, vercelOidc } from "eve/channels/auth";
69
+
70
+ export default eveChannel({ auth: [localDev(), vercelOidc()] });
71
+ ```
72
+
73
+ For a public demo, use `none()` (also from `eve/channels/auth`) to skip authentication. See [Channels](../../channels/overview) and [Auth & route protection](../auth-and-route-protection).
60
74
 
61
75
  ## Dev vs deploy topology
62
76
 
@@ -69,13 +83,13 @@ Before deploying a user-facing app, add `agent/channels/eve.ts` so production re
69
83
  });
70
84
  ```
71
85
 
72
- - **Local production build.** `next build && next start` proxies Eve routes to `http://127.0.0.1:4274`. Change the port with `EVE_NEXT_PRODUCTION_PORT`:
86
+ - **Local production build.** `next build && next start` serves the Eve runtime from its built `.output/server/index.mjs` on a stable local port (`4274`) and proxies the Eve routes to it. Run `eve build` first so that output exists. Change the port with `EVE_NEXT_PRODUCTION_PORT`:
73
87
 
74
88
  ```bash
75
89
  EVE_NEXT_PRODUCTION_PORT=5000 npm run build && npm start
76
90
  ```
77
91
 
78
- - **Non-Vercel hosts.** If the Eve service lives on a separate origin, tell Next.js where to find it with `EVE_NEXT_PRODUCTION_ORIGIN`:
92
+ - **Non-Vercel hosts.** When the Eve service lives on a separate origin, tell Next.js where to find it with `EVE_NEXT_PRODUCTION_ORIGIN`:
79
93
 
80
94
  ```bash
81
95
  EVE_NEXT_PRODUCTION_ORIGIN=https://agent.example.com npm run build
@@ -3,7 +3,13 @@ title: "Nuxt"
3
3
  description: "Run an Eve agent and a Nuxt app as one project with the eve/nuxt module."
4
4
  ---
5
5
 
6
- The `eve/nuxt` module folds a Nuxt frontend and an Eve agent into a single project: one dev server, one Vercel deploy. The auto-imported [`useEveAgent`](./use-eve-agent-vue) composable finds the mounted routes on its own, so you skip the usual CORS headaches and URL env vars.
6
+ The `eve/nuxt` module runs a Nuxt frontend and an Eve agent as a single project from one dev server and one Vercel deploy. The auto-imported [`useEveAgent`](./use-eve-agent-vue) composable finds the mounted routes on its own, so there's no CORS to configure and no URL env vars to keep in sync.
7
+
8
+ ## Prerequisites
9
+
10
+ - The `eve` package installed in your project (`npm install eve@latest`).
11
+ - An existing Eve agent directory. If you don't have one, start from [Getting started](../../getting-started).
12
+ - A Nuxt app to mount the agent in.
7
13
 
8
14
  ## Register the module
9
15
 
@@ -24,9 +30,11 @@ export default defineNuxtConfig({
24
30
  });
25
31
  ```
26
32
 
33
+ The `eve` key accepts only two options, `eveRoot` and `eveBuildCommand`.
34
+
27
35
  ## Call the composable
28
36
 
29
- `useEveAgent` (`eve/vue`) is auto-imported, so a component can call it without an explicit import and without naming a host:
37
+ `useEveAgent` (`eve/vue`) is auto-imported, so a component calls it without an explicit import and without naming a host:
30
38
 
31
39
  ```vue
32
40
  <script setup lang="ts">
@@ -52,7 +60,16 @@ async function handleSubmit() {
52
60
  </template>
53
61
  ```
54
62
 
55
- Out of the box the module gives Eve a framework default channel. When you want to pick the route auth policy yourself, add `agent/channels/eve.ts` and swap `none()` for a helper like `vercelOidc()` on protected apps. See [Channels](../../channels/overview) and [Auth & route protection](../auth-and-route-protection).
63
+ The default Eve channel is fail-closed. With no `agent/channels/eve.ts` authored, Eve registers `eveChannel({ auth: [localDev(), vercelOidc()] })`: `localDev()` opens the routes on localhost, `vercelOidc()` admits Vercel OIDC callers in production, and everything else gets a `401`. To run your own auth policy, add `agent/channels/eve.ts`:
64
+
65
+ ```ts title="agent/channels/eve.ts"
66
+ import { eveChannel } from "eve/channels/eve";
67
+ import { localDev, vercelOidc } from "eve/channels/auth";
68
+
69
+ export default eveChannel({ auth: [localDev(), vercelOidc()] });
70
+ ```
71
+
72
+ For a public demo, use `none()` (also from `eve/channels/auth`) to skip authentication. See [Channels](../../channels/overview) and [Auth & route protection](../auth-and-route-protection).
56
73
 
57
74
  ## Dev vs deploy topology
58
75
 
@@ -68,7 +85,7 @@ Out of the box the module gives Eve a framework default channel. When you want t
68
85
  });
69
86
  ```
70
87
 
71
- - **Non-Vercel hosts.** Point Nuxt at a separate Eve origin with `EVE_NUXT_PRODUCTION_ORIGIN`. To override the local port (it defaults to `4274`), use `EVE_NUXT_PRODUCTION_PORT`:
88
+ - **Non-Vercel hosts.** Point Nuxt at a separate Eve origin with `EVE_NUXT_PRODUCTION_ORIGIN`. To override the local port (default `4274`), use `EVE_NUXT_PRODUCTION_PORT`:
72
89
 
73
90
  ```bash
74
91
  EVE_NUXT_PRODUCTION_ORIGIN=https://agent.example.com npm run build
@@ -3,22 +3,22 @@ title: "Overview"
3
3
  description: "Put an Eve agent behind a browser chat UI with useEveAgent."
4
4
  ---
5
5
 
6
- The frontend helpers put a browser chat or agent UI on top of an Eve agent. `useEveAgent()` does the heavy lifting: it opens a durable session, sends turns, streams the reply back, and turns the raw event stream into render-ready state. React is the reference implementation, and [Vue](./use-eve-agent-vue) and [Svelte](./use-eve-agent-svelte) ship the same surface.
6
+ The frontend helpers put a browser chat or agent UI on top of an Eve agent. `useEveAgent()` opens a durable session, sends turns, streams the reply back, and turns the raw event stream into render-ready state. React is the reference implementation; [Vue](./use-eve-agent-vue) and [Svelte](./use-eve-agent-svelte) ship the same surface.
7
7
 
8
8
  ## The integration model
9
9
 
10
- A browser UI is just a client of the agent's HTTP routes (the [Eve channel](../../channels/overview)). Two layers wire it up:
10
+ A browser UI is a client of the agent's HTTP routes (the [Eve channel](../../channels/overview)). Two layers wire it up:
11
11
 
12
12
  - **The framework integration** mounts the Eve routes on your app's origin, so the browser never crosses a CORS boundary or reads an env var to find the agent. Pick yours: [Next.js](./nextjs) (`withEve`), [Nuxt](./nuxt) (the `eve/nuxt` module), or [SvelteKit](./sveltekit) (the `eveSvelteKit` Vite plugin). On any other stack the hook talks to same-origin `/eve/v1/*` routes directly, or you pass an explicit `host`.
13
13
  - **The hook** (`useEveAgent`) holds the session state, streaming, errors, and composer status. It defaults to same-origin Eve routes such as `/eve/v1/session`.
14
14
 
15
- For a guided setup, the [Guides](/docs/skills/eve-add-next) walk through the wiring step by step: [add a Next.js frontend to an existing Eve agent](/docs/skills/eve-add-next), or [add Eve to an existing Next.js app](/docs/skills/eve-add-agent).
15
+ The per-framework pages below walk through the wiring step by step: [Next.js](./nextjs), [Nuxt](./nuxt), and [SvelteKit](./sveltekit).
16
16
 
17
17
  For scripts, server-to-server calls, evals, tests, or custom clients that do not need framework UI state, use the [TypeScript SDK](../client/overview) directly.
18
18
 
19
19
  ## Basic chat (React)
20
20
 
21
- The hook lives in `eve/react`. Render `data.messages`, gate the composer on `status`, and send text with `send`. That's the whole loop:
21
+ The hook lives in `eve/react`. Render `data.messages`, gate the composer on `status`, and send text with `send`:
22
22
 
23
23
  ```tsx
24
24
  "use client";
@@ -72,7 +72,7 @@ export function Chat() {
72
72
  | `stop` | Abort the active request. |
73
73
  | `reset` | Clear local events, data, errors, and the local session cursor. |
74
74
 
75
- Most chat UIs only need `data.messages` and `status`. Drop down to `events` when you want to render lower-level activity (tool calls, reasoning deltas) that the default reducer doesnt surface.
75
+ Most chat UIs only need `data.messages` and `status`. Drop down to `events` to render lower-level activity such as tool calls and reasoning deltas that the default reducer doesn't surface.
76
76
 
77
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, and input requests.
78
78
 
@@ -96,7 +96,7 @@ await agent.send({
96
96
  });
97
97
  ```
98
98
 
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. Call `reset()` to clear local state so the next send starts a fresh durable session.
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
101
  ## Human-in-the-loop prompts
102
102
 
@@ -115,11 +115,11 @@ if (request) {
115
115
  }
116
116
  ```
117
117
 
118
- `request.prompt` and `request.options` give you what you need to render the approve and deny UI. The default reducer marks the part as responded right away, then updates it again once Eve streams the resumed result.
118
+ `request.prompt` and `request.options` give you what you need to render the approve and deny UI. The default reducer marks the part as responded immediately, then updates it again once Eve streams the resumed result.
119
119
 
120
120
  ## Attach page context per turn
121
121
 
122
- `clientContext` adds ephemeral context for the next model call and nothing more. Strings (or an array of strings) become user-role context messages; an object is JSON-serialized into one. It rides along with a message or HITL response, so it never dispatches a turn on its own and never lands in durable session history. Pass it directly to `send()`:
122
+ `clientContext` adds ephemeral context for the next model call only. Strings (or an array of strings) become user-role context messages; an object is JSON-serialized into one. It rides along with a message or HITL response, so it never dispatches a turn on its own and never lands in durable session history. Pass it directly to `send()`:
123
123
 
124
124
  ```tsx
125
125
  await agent.send({
@@ -182,11 +182,11 @@ const agent = useEveAgent({ reducer: toolCounter });
182
182
  // agent.data is ToolLog
183
183
  ```
184
184
 
185
- `reduce(data, event)` receives both authoritative Eve stream events and client projection events (`client.message.submitted`, `client.message.failed`, `client.input.responded`). Handle the client events too if you want optimistic and HITL state in your projection. Otherwise, just return `data` unchanged for them.
185
+ `reduce(data, event)` receives both authoritative Eve stream events and client projection events (`client.message.submitted`, `client.message.failed`, `client.input.responded`). Handle the client events too if you want optimistic and HITL state in your projection. Otherwise, return `data` unchanged for them.
186
186
 
187
187
  ## Resumable sessions
188
188
 
189
- The browser conversation lives durably on the server. Persist the `session` cursor and you can pick it back up after a reload:
189
+ The browser conversation lives durably on the server. Persist the `session` cursor to pick it back up after a reload:
190
190
 
191
191
  ```tsx
192
192
  const [initialSession] = useState(() => {
@@ -231,4 +231,4 @@ const agent = useEveAgent({
231
231
  - [Sessions, runs & streaming](../../concepts/sessions-runs-and-streaming): the event stream and session cursor
232
232
  - [Channels](../../channels/overview): the HTTP routes the hook talks to
233
233
  - [TypeScript SDK](../client/overview): the lower-level client underneath the frontend hooks
234
- - [Guides](/docs/skills/eve-add-next): step-by-step guides for wiring Eve into Next.js
234
+ - [Next.js](./nextjs): step-by-step setup for wiring Eve into a Next.js app
@@ -3,7 +3,13 @@ title: "SvelteKit"
3
3
  description: "Run an Eve agent and a SvelteKit app as one project with the eveSvelteKit Vite plugin."
4
4
  ---
5
5
 
6
- `eve/sveltekit` lets you run a SvelteKit frontend and an Eve agent as one project instead of two services you have to keep in sync. The `eveSvelteKit()` Vite plugin puts both on one dev server and one Vercel deploy, and [`useEveAgent`](./use-eve-agent-svelte) finds the mounted routes on its own. No CORS config, no URL env vars.
6
+ `eve/sveltekit` runs a SvelteKit frontend and an Eve agent as one project instead of two services. The `eveSvelteKit()` Vite plugin puts both on one dev server and one Vercel deploy, and [`useEveAgent`](./use-eve-agent-svelte) finds the mounted routes on its own. There's no CORS to configure and no URL env vars to keep in sync.
7
+
8
+ ## Prerequisites
9
+
10
+ - The `eve` package installed in your project (`npm install eve@latest`).
11
+ - An existing Eve agent directory. If you don't have one, start from [Getting started](../../getting-started).
12
+ - A SvelteKit app to mount the agent in.
7
13
 
8
14
  ## Register the Vite plugin
9
15
 
@@ -32,6 +38,8 @@ export default defineConfig({
32
38
  });
33
39
  ```
34
40
 
41
+ The plugin accepts only two options, `eveRoot` and `eveBuildCommand`.
42
+
35
43
  ## Call the binding
36
44
 
37
45
  With the plugin in `vite.config.ts`, components call [`useEveAgent`](./use-eve-agent-svelte) from `eve/svelte` and don't pass a host:
@@ -61,11 +69,20 @@ With the plugin in `vite.config.ts`, components call [`useEveAgent`](./use-eve-a
61
69
  </form>
62
70
  ```
63
71
 
64
- Out of the box the plugin uses a framework default channel. To set the route auth policy yourself, add `agent/channels/eve.ts` and swap `none()` for a helper like `vercelOidc()` on protected apps. See [Channels](../../channels/overview) and [Auth & route protection](../auth-and-route-protection).
72
+ The default Eve channel is fail-closed. With no `agent/channels/eve.ts` authored, Eve registers `eveChannel({ auth: [localDev(), vercelOidc()] })`: `localDev()` opens the routes on localhost, `vercelOidc()` admits Vercel OIDC callers in production, and everything else gets a `401`. To set your own auth policy, add `agent/channels/eve.ts`:
73
+
74
+ ```ts title="agent/channels/eve.ts"
75
+ import { eveChannel } from "eve/channels/eve";
76
+ import { localDev, vercelOidc } from "eve/channels/auth";
77
+
78
+ export default eveChannel({ auth: [localDev(), vercelOidc()] });
79
+ ```
80
+
81
+ For a public demo, use `none()` (also from `eve/channels/auth`) to skip authentication. See [Channels](../../channels/overview) and [Auth & route protection](../auth-and-route-protection).
65
82
 
66
83
  ## Dev vs deploy topology
67
84
 
68
- - **Local dev.** `npm run dev` boots the Eve dev server next to SvelteKit and proxies the Eve routes to it, so the browser only ever hits the SvelteKit origin. `npm run build && npm run preview` behaves the same: the preview server gets its own Eve route proxy and either reuses the shared Eve server or starts one.
85
+ - **Local dev.** `npm run dev` boots the Eve dev server next to SvelteKit and proxies the Eve routes to it, so the browser only ever hits the SvelteKit origin. `npm run build && npm run preview` behaves the same way: the preview server gets its own Eve route proxy and either reuses the shared Eve server or starts one.
69
86
  - **Vercel.** The SvelteKit app and the Eve runtime deploy as a single project. The web app is public; the Eve runtime sits behind it on the same origin. Use `eveBuildCommand` for a project-specific agent build:
70
87
 
71
88
  ```ts