eve 0.9.8 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/README.md +14 -0
- package/dist/src/cli/banner.d.ts +6 -3
- package/dist/src/cli/banner.js +1 -1
- package/dist/src/cli/commands/init.js +1 -1
- package/dist/src/cli/dev/tui/agent-header.js +1 -1
- package/dist/src/cli/run.js +1 -1
- package/dist/src/evals/runner/run-evals.d.ts +1 -1
- package/dist/src/harness/input-requests.d.ts +20 -1
- package/dist/src/harness/input-requests.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/protocol/message.d.ts +11 -2
- package/dist/src/protocol/message.js +2 -2
- package/dist/src/public/next/index.d.ts +1 -7
- package/dist/src/public/next/index.js +1 -1
- package/dist/src/public/next/vercel-output-config.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/setup/scaffold/create/web-template.d.ts +1 -1
- package/dist/src/setup/scaffold/create/web-template.js +27 -4
- package/dist/src/setup/scaffold/update/channels.js +1 -1
- package/docs/README.md +19 -5
- package/docs/agent-config.md +16 -19
- package/docs/channels/custom.mdx +24 -18
- package/docs/channels/discord.mdx +25 -13
- package/docs/channels/eve.mdx +24 -6
- package/docs/channels/github.mdx +41 -10
- package/docs/channels/linear.mdx +29 -36
- package/docs/channels/overview.mdx +16 -4
- package/docs/channels/slack.mdx +59 -32
- package/docs/channels/teams.mdx +19 -7
- package/docs/channels/telegram.mdx +23 -9
- package/docs/channels/twilio.mdx +28 -6
- package/docs/concepts/context-control.md +24 -41
- package/docs/concepts/default-harness.md +19 -9
- package/docs/concepts/execution-model-and-durability.md +14 -14
- package/docs/concepts/security-model.md +32 -8
- package/docs/concepts/sessions-runs-and-streaming.md +11 -9
- package/docs/connections.mdx +49 -29
- package/docs/evals/assertions.mdx +30 -29
- package/docs/evals/cases.mdx +10 -10
- package/docs/evals/judge.mdx +14 -14
- package/docs/evals/overview.mdx +15 -17
- package/docs/evals/reporters.mdx +19 -7
- package/docs/evals/running.mdx +2 -2
- package/docs/evals/targets.mdx +15 -4
- package/docs/getting-started.mdx +70 -31
- package/docs/guides/auth-and-route-protection.md +18 -12
- package/docs/guides/client/continuations.mdx +5 -13
- package/docs/guides/client/messages.mdx +2 -2
- package/docs/guides/client/output-schema.mdx +2 -2
- package/docs/guides/client/overview.mdx +4 -4
- package/docs/guides/client/streaming.mdx +6 -5
- package/docs/guides/deployment.md +22 -20
- package/docs/guides/dev-tui.md +85 -13
- package/docs/guides/dynamic-capabilities.md +24 -8
- package/docs/guides/dynamic-workflows.md +33 -12
- package/docs/guides/frontend/nextjs.mdx +28 -14
- package/docs/guides/frontend/nuxt.mdx +21 -4
- package/docs/guides/frontend/overview.mdx +11 -11
- package/docs/guides/frontend/sveltekit.mdx +20 -3
- package/docs/guides/frontend/use-eve-agent-svelte.mdx +106 -14
- package/docs/guides/frontend/use-eve-agent-vue.mdx +108 -15
- package/docs/guides/hooks.md +14 -60
- package/docs/guides/instrumentation.md +24 -18
- package/docs/guides/remote-agents.md +19 -15
- package/docs/guides/session-context.md +12 -12
- package/docs/guides/state.md +25 -9
- package/docs/instructions.mdx +18 -10
- package/docs/introduction.md +12 -12
- package/docs/legal.md +16 -0
- package/docs/meta.json +1 -0
- package/docs/reference/cli.md +101 -53
- package/docs/reference/meta.json +1 -1
- package/docs/reference/project-layout.md +39 -32
- package/docs/reference/typescript-api.md +1 -1
- package/docs/sandbox.mdx +25 -19
- package/docs/schedules.mdx +16 -14
- package/docs/skills.mdx +8 -6
- package/docs/subagents.mdx +39 -13
- package/docs/tools.mdx +13 -9
- package/docs/tutorial/connect-a-warehouse.mdx +16 -7
- package/docs/tutorial/first-agent.mdx +21 -11
- package/docs/tutorial/guard-the-spend.mdx +11 -9
- package/docs/tutorial/how-it-runs.mdx +10 -8
- package/docs/tutorial/query-sample-data.mdx +8 -8
- package/docs/tutorial/remember-definitions.mdx +5 -5
- package/docs/tutorial/run-analysis.mdx +13 -11
- package/docs/tutorial/ship-it.mdx +70 -14
- package/docs/tutorial/team-playbooks.mdx +33 -10
- package/package.json +1 -1
package/docs/getting-started.mdx
CHANGED
|
@@ -3,30 +3,48 @@ title: "Getting Started"
|
|
|
3
3
|
description: "Install Eve, scaffold your first agent, give it a tool, and run it locally."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
Eve is a filesystem-first framework for durable agents
|
|
6
|
+
Eve is a filesystem-first framework for durable agents. You write capabilities under `agent/`, and Eve runs the model loop, persists every session, and serves the agent over HTTP and platform channels. You'll scaffold an app, add a tool, run it locally, then create, stream, and continue a session over HTTP.
|
|
7
|
+
|
|
8
|
+
Eve is currently in beta and subject to the [Vercel beta terms](https://vercel.com/docs/release-phases/public-beta-agreement). The framework, APIs, documentation, and behavior may change before general availability.
|
|
9
|
+
|
|
10
|
+
## Prerequisites
|
|
11
|
+
|
|
12
|
+
- Node 24 or newer
|
|
13
|
+
- npm (bundled with Node)
|
|
14
|
+
- A model credential (see below)
|
|
15
|
+
|
|
16
|
+
The scaffold's default model is `anthropic/claude-sonnet-4.6`, which routes through the Vercel AI Gateway. Set one of these before you run the agent:
|
|
17
|
+
|
|
18
|
+
- A gateway model id needs `AI_GATEWAY_API_KEY`, or a `VERCEL_OIDC_TOKEN` pulled with `vercel link`.
|
|
19
|
+
- A direct provider id needs that provider's key, derived from the model prefix. For example, `anthropic/claude-...` needs `ANTHROPIC_API_KEY`.
|
|
20
|
+
|
|
21
|
+
You are responsible for selecting a model, provider, and channel appropriate for your data and use case, and for complying with each provider's terms (as listed per model) and data-processing requirements.
|
|
22
|
+
|
|
23
|
+
If you skip this, the dev TUI flags the missing credential and its `/model` command walks you through pasting a key or linking a project.
|
|
7
24
|
|
|
8
25
|
## Quick start
|
|
9
26
|
|
|
10
|
-
|
|
27
|
+
`npx` runs `eve init` without installing Eve first:
|
|
11
28
|
|
|
12
29
|
```bash
|
|
13
30
|
npx eve@latest init my-agent
|
|
14
31
|
```
|
|
15
32
|
|
|
16
|
-
The command
|
|
33
|
+
The command:
|
|
17
34
|
|
|
18
|
-
|
|
35
|
+
- Creates an npm-managed child directory and uses Eve's default model
|
|
36
|
+
- Installs dependencies and initializes Git
|
|
37
|
+
- Starts the development server and opens the interactive [terminal UI](./guides/dev-tui)
|
|
19
38
|
|
|
20
|
-
-
|
|
21
|
-
- npm (bundled with Node)
|
|
39
|
+
Type a message and watch the model loop run. Pass `--channel-web-nextjs` to add the Web Chat application. Every app ships the built-in HTTP channel (`agent/channels/eve.ts`) regardless.
|
|
22
40
|
|
|
23
|
-
|
|
41
|
+
`eve init` holds the terminal, so stop it with Ctrl+C to get your shell back before editing the generated agent. The command does not create a Vercel project or deploy.
|
|
24
42
|
|
|
25
|
-
|
|
43
|
+
To add Eve to an existing project, run `eve init .` from a directory that already has a `package.json` and no `agent/` files yet. Eve adds the missing `eve`, `ai`, and `zod` dependencies without touching anything else the project owns. The Eve dependency and the Node engine come from the same release. Eve pins `engines.node` to the lowest major that release supports (for example `24.x`). It keeps an existing range only when every version that range allows stays within that major; otherwise it replaces the range and prints a warning.
|
|
26
44
|
|
|
27
|
-
|
|
45
|
+
## Manual installation
|
|
28
46
|
|
|
29
|
-
To wire Eve
|
|
47
|
+
To wire Eve into an existing app by hand instead of using `eve init`, first declare a compatible Node runtime in `package.json`:
|
|
30
48
|
|
|
31
49
|
```json
|
|
32
50
|
{
|
|
@@ -36,10 +54,10 @@ To wire Eve in by hand, declare a compatible Node runtime in `package.json`:
|
|
|
36
54
|
}
|
|
37
55
|
```
|
|
38
56
|
|
|
39
|
-
Then install
|
|
57
|
+
Then install the dependencies and author the two files the runtime needs. The `eve init` scaffold adds `ai` and `zod` for you; by hand you install all three:
|
|
40
58
|
|
|
41
59
|
```bash
|
|
42
|
-
npm install eve@latest
|
|
60
|
+
npm install eve@latest ai zod
|
|
43
61
|
```
|
|
44
62
|
|
|
45
63
|
### Project files
|
|
@@ -62,18 +80,19 @@ export default defineAgent({
|
|
|
62
80
|
});
|
|
63
81
|
```
|
|
64
82
|
|
|
83
|
+
Before using real customer data, confirm the selected model provider's terms, routing path, and retention settings are appropriate for that data.
|
|
84
|
+
|
|
65
85
|
Even at this size the agent can already do real work. The default harness gives it file, shell, web, and delegation tools out of the box. See [Default harness](./concepts/default-harness) for the full set and how to override or disable any of them.
|
|
66
86
|
|
|
67
87
|
### Add your first tool
|
|
68
88
|
|
|
69
|
-
|
|
89
|
+
The filename becomes the tool name the model sees, and it must be snake_case ASCII. Create `agent/tools/get_weather.ts`:
|
|
70
90
|
|
|
71
91
|
```ts
|
|
72
92
|
import { defineTool } from "eve/tools";
|
|
73
93
|
import { z } from "zod";
|
|
74
94
|
|
|
75
|
-
// The
|
|
76
|
-
// `get_weather`. Tool filenames must be snake_case ASCII.
|
|
95
|
+
// The model sees this tool as `get_weather`, from the filename.
|
|
77
96
|
export default defineTool({
|
|
78
97
|
description: "Get the current weather for a city.",
|
|
79
98
|
inputSchema: z.object({ city: z.string().min(1) }),
|
|
@@ -87,29 +106,35 @@ Tools run in your app runtime with full `process.env`, not inside the [sandbox](
|
|
|
87
106
|
|
|
88
107
|
## Run the app
|
|
89
108
|
|
|
90
|
-
|
|
109
|
+
A scaffolded app has a `dev` script, so from the app root run:
|
|
91
110
|
|
|
92
111
|
```bash
|
|
93
112
|
npm run dev
|
|
94
113
|
```
|
|
95
114
|
|
|
96
|
-
|
|
115
|
+
The manual path authors no `dev` script. Run the binary through `npx` instead:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
npx eve dev
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Other commands the eve binary provides (prefix each with `npx`, or add a matching package.json script):
|
|
97
122
|
|
|
98
123
|
- `eve info`: show the active routes and compiled artifacts
|
|
99
124
|
- `eve build`: compile the agent into `.eve/` and build the host output
|
|
100
125
|
- `eve start`: serve the built output
|
|
101
126
|
- `eve dev`: start the local runtime and open the interactive [terminal UI](./guides/dev-tui)
|
|
102
127
|
|
|
103
|
-
In the dev TUI, type a message and watch it happen in order
|
|
128
|
+
In the dev TUI, type a message and watch it happen in order. First the `get_weather` call, then its result, then the reply.
|
|
104
129
|
|
|
105
|
-
The same CLI can point at a deployment. `eve dev https://your-app.vercel.app` drives a deployed app, which is handy for preview and production smoke tests. See [Deployment](./guides/deployment).
|
|
130
|
+
The same CLI can point at a deployment. `npx eve dev https://your-app.vercel.app` drives a deployed app, which is handy for preview and production smoke tests. See [Deployment](./guides/deployment).
|
|
106
131
|
|
|
107
132
|
## Send a message
|
|
108
133
|
|
|
109
134
|
Every Eve app exposes the same stable HTTP API. Start a durable session:
|
|
110
135
|
|
|
111
136
|
```bash
|
|
112
|
-
curl -X POST http://127.0.0.1:
|
|
137
|
+
curl -X POST http://127.0.0.1:3000/eve/v1/session \
|
|
113
138
|
-H 'content-type: application/json' \
|
|
114
139
|
-d '{"message":"What is the weather in Brooklyn?"}'
|
|
115
140
|
```
|
|
@@ -124,35 +149,49 @@ The response comes back with two things you'll reuse:
|
|
|
124
149
|
Attach to the session stream:
|
|
125
150
|
|
|
126
151
|
```bash
|
|
127
|
-
curl http://127.0.0.1:
|
|
152
|
+
curl http://127.0.0.1:3000/eve/v1/session/<sessionId>/stream
|
|
128
153
|
```
|
|
129
154
|
|
|
130
|
-
The stream is NDJSON,
|
|
155
|
+
The stream is NDJSON, served as `application/x-ndjson; charset=utf-8`. For this run you'll see a handful of lifecycle events:
|
|
156
|
+
|
|
157
|
+
- `session.started`
|
|
158
|
+
- `actions.requested` (the `get_weather` call)
|
|
159
|
+
- `action.result`
|
|
160
|
+
- `message.completed` (the reply)
|
|
161
|
+
- `session.completed`
|
|
162
|
+
|
|
163
|
+
`reasoning.appended` and `message.appended` are optional live-streaming events. Clients that can't surface incremental output can ignore them and rely on `reasoning.completed` and `message.completed`.
|
|
164
|
+
|
|
165
|
+
Note: consider the privacy, confidentiality, and user-experience implications for displaying, storing, or transmitting reasoning events in your application.
|
|
166
|
+
|
|
167
|
+
The full set covers more lifecycle, human-in-the-loop, and authorization events, including `input.requested`, `turn.failed`, `authorization.required`, and `authorization.completed`. See [Sessions, runs and streaming](./concepts/sessions-runs-and-streaming) for every event and its data shape.
|
|
131
168
|
|
|
132
169
|
## Send a follow-up message
|
|
133
170
|
|
|
134
171
|
When the session is waiting for the next user message, post a follow-up with the token:
|
|
135
172
|
|
|
136
173
|
```bash
|
|
137
|
-
curl -X POST http://127.0.0.1:
|
|
174
|
+
curl -X POST http://127.0.0.1:3000/eve/v1/session/<sessionId> \
|
|
138
175
|
-H 'content-type: application/json' \
|
|
139
176
|
-d '{"continuationToken":"<token>","message":"Now do Queens."}'
|
|
140
177
|
```
|
|
141
178
|
|
|
142
|
-
See [Sessions, runs
|
|
179
|
+
See [Sessions, runs and streaming](./concepts/sessions-runs-and-streaming) for the full contract.
|
|
143
180
|
|
|
144
181
|
## Setting up with a coding agent
|
|
145
182
|
|
|
146
183
|
If a coding agent (Claude Code, Cursor, and the like) is doing the setup, hand it this prompt:
|
|
147
184
|
|
|
148
|
-
<CopyPrompt text="Set up an Eve agent for the user.
|
|
149
|
-
Set up an Eve agent
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
185
|
+
<CopyPrompt text="Set up an Eve agent for the user. Eve is a filesystem-first TypeScript framework for durable agents, published as the npm package eve. Read its docs: once eve is installed they are bundled in the package at node_modules/eve/docs; before eve is installed, read the published Introduction and Getting Started pages. If the project has no Eve app, scaffold one with `npx eve@latest init <name>`; add `--channel-web-nextjs` only when the user wants Web Chat. The init command installs dependencies, initializes Git, and starts the dev server, so run it in a controllable process and stop it with Ctrl+C before editing. To add Eve to an existing app, run `eve init .`, or install the dependencies by hand with `npm install eve@latest ai zod` (init adds ai and zod; the by-hand path needs all three). Make sure agent/agent.ts and agent/instructions.md exist, then add a first typed tool at agent/tools/get_weather.ts using defineTool from eve/tools with a Zod inputSchema and an inline execute. Start the dev server again, then exercise the HTTP API: create a session with POST /eve/v1/session, attach to GET /eve/v1/session/:id/stream, and send a follow-up with the returned continuationToken. Verify with the project's typecheck, adapt model and provider choices to the project, and do not commit unless the user asks.">
|
|
186
|
+
Set up an Eve agent: read the Eve docs (bundled at node_modules/eve/docs once eve is
|
|
187
|
+
installed), scaffold with `npx eve@latest init <name>` (or `npm install eve@latest ai zod` in an existing app), add
|
|
188
|
+
a typed tool at agent/tools/get_weather.ts, run it with `npm run dev`, then create a session, stream
|
|
189
|
+
it, and send a follow-up.
|
|
153
190
|
</CopyPrompt>
|
|
154
191
|
|
|
155
|
-
Once `eve` is
|
|
192
|
+
Once `eve` is a dependency, the package bundles the full docs, so the agent can read them locally at `node_modules/eve/docs/` without fetching anything.
|
|
193
|
+
|
|
194
|
+
To add a platform channel after setup, run `eve channels add slack` from an interactive terminal. The init flags are covered in [Quick start](#quick-start).
|
|
156
195
|
|
|
157
196
|
## What to read next
|
|
158
197
|
|
|
@@ -160,5 +199,5 @@ Once `eve` is installed, the complete docs ship at `node_modules/eve/docs/`, so
|
|
|
160
199
|
- [Channels](./channels/overview): reach the agent from Slack, Discord, or a web UI
|
|
161
200
|
- [Frontend](./guides/frontend/overview): browser chat with `useEveAgent`
|
|
162
201
|
- [TypeScript SDK](./guides/client/overview): call the agent from scripts or server-side code
|
|
163
|
-
- [Sessions, runs
|
|
202
|
+
- [Sessions, runs and streaming](./concepts/sessions-runs-and-streaming): the durable session model
|
|
164
203
|
- [Build an agent](./tutorial/first-agent): the full end-to-end walkthrough
|
|
@@ -3,21 +3,23 @@ title: "Auth & Route Protection"
|
|
|
3
3
|
description: "Secure your agent's HTTP routes with an ordered auth walk, verifier helpers, and connection OAuth via Vercel Connect."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
Eve has two
|
|
6
|
+
Eve has two independent auth systems:
|
|
7
7
|
|
|
8
|
-
- **Route auth** (inbound)
|
|
9
|
-
- **Tool and connection auth** (outbound)
|
|
8
|
+
- **Route auth** (inbound) decides who can reach your agent's HTTP routes. It runs at the channel layer, gating the request before any model work runs.
|
|
9
|
+
- **Tool and connection auth** (outbound) is how your agent signs in to an external service it calls, like an OAuth MCP server. It happens later, when a tool or connection actually reaches out.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Start with route auth.
|
|
12
12
|
|
|
13
13
|
## Route auth
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
The route-auth policy lives on the HTTP channel factory (`agent/channels/eve.ts`) and guards three routes:
|
|
16
16
|
|
|
17
17
|
- `POST /eve/v1/session`
|
|
18
18
|
- `POST /eve/v1/session/:sessionId`
|
|
19
19
|
- `GET /eve/v1/session/:sessionId/stream`
|
|
20
20
|
|
|
21
|
+
These routes are protected by the channel's auth policy. Eve fails closed by default: production browser traffic is rejected unless you configure an authenticator that accepts it, and anonymous access requires an explicit `none()`.
|
|
22
|
+
|
|
21
23
|
`GET /eve/v1/health` is always public and skips the walk entirely, so load balancers and uptime monitors can probe it without credentials.
|
|
22
24
|
|
|
23
25
|
```ts title="agent/channels/eve.ts"
|
|
@@ -64,7 +66,7 @@ export default eveChannel({
|
|
|
64
66
|
|
|
65
67
|
Put your own providers ahead of the catch-all helpers. Any entry that doesn't recognize the caller returns `null`, and the walk moves on.
|
|
66
68
|
|
|
67
|
-
|
|
69
|
+
To reject with a precise status instead of skipping, throw:
|
|
68
70
|
|
|
69
71
|
```ts
|
|
70
72
|
import { ForbiddenError, UnauthenticatedError } from "eve/channels/auth";
|
|
@@ -76,7 +78,7 @@ throw new UnauthenticatedError({
|
|
|
76
78
|
throw new ForbiddenError({ message: "Not allowed on this workspace." }); // 403
|
|
77
79
|
```
|
|
78
80
|
|
|
79
|
-
Any other thrown error follows the normal channel failure path.
|
|
81
|
+
Any other thrown error follows the normal channel failure path. When building a custom channel on `defineChannel`, call `routeAuth(request, auth)` from `eve/channels/auth` to reuse the same walk semantics.
|
|
80
82
|
|
|
81
83
|
## Verifier helpers
|
|
82
84
|
|
|
@@ -92,6 +94,8 @@ Any other thrown error follows the normal channel failure path. Building a custo
|
|
|
92
94
|
| `jwtEcdsa(...)` | You verify asymmetric JWTs minted by another system. |
|
|
93
95
|
| `oidc(...)` | You want Eve to verify OIDC-issued tokens from an arbitrary issuer. |
|
|
94
96
|
|
|
97
|
+
Exercise caution for agents that process non-public, sensitive, regulated, or production data unless you have implemented other access controls.
|
|
98
|
+
|
|
95
99
|
### `localDev()`
|
|
96
100
|
|
|
97
101
|
Authenticates a synthetic `local-dev` principal, but only when the inbound request is addressed to a loopback hostname (`localhost`, `*.localhost`, `127.0.0.0/8`, or `::1`). The check keys off the request URL's hostname rather than the bare `process.env.VERCEL` flag, and that's deliberate: a deployment outside Vercel leaves `VERCEL` unset, so sniffing that flag alone would wave through all public traffic. There's one process-level exception. `vercel dev`, detected by `VERCEL=1` and `VERCEL_ENV=development` together, opens the local dev server even when it serves over a non-loopback host. Every other non-loopback request returns `null` and falls through.
|
|
@@ -106,7 +110,7 @@ Auth fails closed: routes reject unauthenticated traffic by default, and the OID
|
|
|
106
110
|
|
|
107
111
|
#### `subjects` patterns and `vercelSubject(...)`
|
|
108
112
|
|
|
109
|
-
Each `subjects` entry is matched against the token's `sub` claim, which Vercel shapes as `owner:<team>:project:<name>:environment:<env>`. Hand-writing that string is a footgun: a typo silently rejects every caller, and an over-broad `*` wildcard silently lets unrelated ones in. Build the pattern with `vercelSubject(...)` instead. It rejects malformed input at construction time and
|
|
113
|
+
Each `subjects` entry is matched against the token's `sub` claim, which Vercel shapes as `owner:<team>:project:<name>:environment:<env>`. Hand-writing that string is a footgun: a typo silently rejects every caller, and an over-broad `*` wildcard silently lets unrelated ones in. Build the pattern with `vercelSubject(...)` instead. It rejects malformed input at construction time, and defaults `environment` to `"production"` when you omit it, so an unspecified environment cannot silently accept preview or development tokens:
|
|
110
114
|
|
|
111
115
|
```ts
|
|
112
116
|
import { vercelOidc, vercelSubject } from "eve/channels/auth";
|
|
@@ -205,14 +209,16 @@ Inside runtime code, `ctx.session.auth` carries the result of the channel's rout
|
|
|
205
209
|
|
|
206
210
|
- `auth.current`: the caller on the active inbound turn.
|
|
207
211
|
- `auth.initiator`: the caller that started the durable session.
|
|
208
|
-
- A follow-up message updates `auth.current` but leaves `auth.initiator` alone.
|
|
212
|
+
- A follow-up message updates `auth.current` but leaves `auth.initiator` alone. When a different caller follows up on the same session, `auth.current` tracks the new caller for that turn while `auth.initiator` stays pinned to whoever started it.
|
|
209
213
|
- Both are `null` only on internal runtime paths (subagents, for instance) that never went through an authored route. HTTP traffic always populates `auth.current`, since the walk either accepts with a `SessionAuthContext` or returns `401`.
|
|
210
214
|
|
|
211
|
-
Use the principal on `auth.current` (or `auth.initiator`) to scope tools, resolve [dynamic capabilities](./dynamic-capabilities) per principal, or enforce tenant boundaries. There's no second per-session ownership ACL stacked on top of route auth
|
|
215
|
+
Use the principal on `auth.current` (or `auth.initiator`) to scope tools, resolve [dynamic capabilities](./dynamic-capabilities) per principal, or enforce tenant boundaries. There's no second per-session ownership ACL stacked on top of route auth. Access is decided at the HTTP boundary, and the durable session carries the caller snapshot forward into your runtime code.
|
|
216
|
+
|
|
217
|
+
Route auth does not enforce session ownership. If multiple users or tenants can reach the same route, you must implement the per-user, per-tenant, or per-session authorization your application requires.
|
|
212
218
|
|
|
213
219
|
## Tool and connection auth
|
|
214
220
|
|
|
215
|
-
|
|
221
|
+
Tool and connection auth is how your agent reaches an external service that wants an interactive sign-in, like an OAuth MCP server. Both a connection and an individual tool can declare an `auth` strategy; Eve drives the sign-in, caches the token per step, and re-runs the call once the caller authorizes.
|
|
216
222
|
|
|
217
223
|
### On a connection
|
|
218
224
|
|
|
@@ -263,7 +269,7 @@ Declaring `auth` adds two accessors to the tool's `ctx`:
|
|
|
263
269
|
|
|
264
270
|
Throw `ConnectionAuthorizationRequiredError` anywhere in `execute` (directly, via `requireAuth()`, or implicitly from `getToken()`) and you trigger the consent flow, keyed by the tool's name. Calling either accessor on a tool that does not declare `auth` throws.
|
|
265
271
|
|
|
266
|
-
By default the sign-in affordance title-cases the tool's path-derived name
|
|
272
|
+
By default the sign-in affordance title-cases the tool's path-derived name, so a tool file named `sfdc_lookup.ts` renders "Sign in with Sfdc_lookup". Set `displayName` on the `auth` definition to control what users see instead, for example `auth: { ...connect("sfdc"), displayName: "Salesforce" }`. It is presentation-only. The tool's name still keys the authorization scope, token cache, and callback URL, and a definition-level `displayName` wins over one the strategy stamps on the challenge.
|
|
267
273
|
|
|
268
274
|
## What to read next
|
|
269
275
|
|
|
@@ -3,12 +3,12 @@ title: "Continuations"
|
|
|
3
3
|
description: "Persist and resume Eve client sessions with continuation tokens, session IDs, and stream cursors."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
Eve
|
|
6
|
+
Every Eve client turn returns two handles, and mixing them up is a common mistake. The TypeScript client tracks both for you:
|
|
7
7
|
|
|
8
8
|
- `continuationToken`: the resume handle. Use it to send the next user turn.
|
|
9
9
|
- `sessionId`: the stream-and-inspect handle. Use it to attach to event history.
|
|
10
10
|
|
|
11
|
-
`ClientSession` also tracks `streamIndex`, the count of events already consumed. Together
|
|
11
|
+
`ClientSession` also tracks `streamIndex`, the count of events already consumed. Together these three fields make a `SessionState`.
|
|
12
12
|
|
|
13
13
|
## Read and persist state
|
|
14
14
|
|
|
@@ -75,7 +75,7 @@ if (result.status === "completed") {
|
|
|
75
75
|
}
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
This matches the runtime contract
|
|
78
|
+
This matches the runtime contract, where only waiting sessions can accept the next user input.
|
|
79
79
|
|
|
80
80
|
## Multiple sessions
|
|
81
81
|
|
|
@@ -99,7 +99,7 @@ The shared `Client` only owns host, auth, headers, and reconnect settings. Conve
|
|
|
99
99
|
|
|
100
100
|
## Reconnect an existing stream
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
When a session already has a `sessionId`, `session.stream()` reattaches to its stream from the saved cursor. Resuming a saved `SessionState` after a restart is the common reason to do this:
|
|
103
103
|
|
|
104
104
|
```ts
|
|
105
105
|
const session = client.session(savedState);
|
|
@@ -109,15 +109,7 @@ for await (const event of session.stream()) {
|
|
|
109
109
|
}
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
```ts
|
|
115
|
-
for await (const event of session.stream({ startIndex: 0 })) {
|
|
116
|
-
console.log(event.type);
|
|
117
|
-
}
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
`stream()` is for attaching to an existing run. To send new user input, use `send()`.
|
|
112
|
+
`stream()` attaches to an existing run; to send new user input, use `send()`. For overriding the cursor with `startIndex` and the full reconnection model, see [Streaming](./streaming#open-a-stream-manually).
|
|
121
113
|
|
|
122
114
|
## What to read next
|
|
123
115
|
|
|
@@ -12,7 +12,7 @@ Pass a string to `send()` for plain text:
|
|
|
12
12
|
```ts
|
|
13
13
|
import { Client } from "eve/client";
|
|
14
14
|
|
|
15
|
-
const client = new Client({ host: "http://127.0.0.1:
|
|
15
|
+
const client = new Client({ host: "http://127.0.0.1:3000" });
|
|
16
16
|
const session = client.session();
|
|
17
17
|
|
|
18
18
|
const response = await session.send("What is the weather in Brooklyn?");
|
|
@@ -34,7 +34,7 @@ console.log(result.status, result.message);
|
|
|
34
34
|
| `sessionId` | Session ID for streaming and inspection. |
|
|
35
35
|
| `data` | Structured output when the turn requested an [output schema](./output-schema). |
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
When the stream includes `session.failed`, the turn returns `status: "failed"` rather than throwing. Transport and route errors throw `ClientError`.
|
|
38
38
|
|
|
39
39
|
## Send a full turn payload
|
|
40
40
|
|
|
@@ -3,7 +3,7 @@ title: "Output Schema"
|
|
|
3
3
|
description: "Request structured results from Eve client turns and read typed data from MessageResult."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
Pass `outputSchema` on a client turn when the caller needs structured data instead of only assistant text. The runtime makes the model satisfy the schema before the turn settles
|
|
6
|
+
Pass `outputSchema` on a client turn when the caller needs structured data instead of only assistant text. The runtime makes the model satisfy the schema before the turn settles, then emits the final payload as `result.completed`.
|
|
7
7
|
|
|
8
8
|
## JSON Schema
|
|
9
9
|
|
|
@@ -26,7 +26,7 @@ const outputSchema = {
|
|
|
26
26
|
required: ["title", "count"],
|
|
27
27
|
} as const;
|
|
28
28
|
|
|
29
|
-
const client = new Client({ host: "http://127.0.0.1:
|
|
29
|
+
const client = new Client({ host: "http://127.0.0.1:3000" });
|
|
30
30
|
const session = client.session();
|
|
31
31
|
|
|
32
32
|
const response = await session.send<Summary>({
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "Overview"
|
|
2
|
+
title: "TypeScript SDK Overview"
|
|
3
3
|
description: "Call an Eve agent from TypeScript with Client, sessions, auth, and health checks."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
The `eve/client` entrypoint is the typed client for Eve's default HTTP API. Use it from scripts, server-to-server integrations, tests, evals, backend jobs, or custom UIs that want the session protocol without hand-writing the POST and NDJSON stream loop.
|
|
6
|
+
The `eve/client` entrypoint is the typed client for Eve's default HTTP API. Use it from scripts, server-to-server integrations, tests, evals, backend jobs, or custom UIs that want the session protocol without hand-writing the POST and NDJSON (newline-delimited JSON) stream loop.
|
|
7
7
|
|
|
8
8
|
For browser chat UIs, start with [`useEveAgent`](../frontend/overview). For wire-level details, read [Sessions, runs & streaming](../../concepts/sessions-runs-and-streaming). The client sits between those two: lower level than the frontend hooks, higher level than raw HTTP.
|
|
9
9
|
|
|
@@ -15,11 +15,11 @@ A `Client` binds one host, auth policy, header policy, and stream reconnection b
|
|
|
15
15
|
import { Client } from "eve/client";
|
|
16
16
|
|
|
17
17
|
const client = new Client({
|
|
18
|
-
host: "http://127.0.0.1:
|
|
18
|
+
host: "http://127.0.0.1:3000",
|
|
19
19
|
});
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
`host` is the origin where the Eve routes are mounted. In a same-origin browser integration this is often `""
|
|
22
|
+
`host` is the origin where the Eve routes are mounted. In a same-origin browser integration this is often `""`; scripts and backend services usually name the full URL.
|
|
23
23
|
|
|
24
24
|
## Check health
|
|
25
25
|
|
|
@@ -3,7 +3,7 @@ title: "Streaming"
|
|
|
3
3
|
description: "Consume Eve client stream events live, reconnect by event index, and aggregate turn results."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
Every send
|
|
6
|
+
Every `ClientSession.send()` call posts the turn, then reads the session's NDJSON (newline-delimited JSON) event stream. `MessageResponse` gives you two ways to consume that stream, aggregating it with `result()` or iterating it live.
|
|
7
7
|
|
|
8
8
|
## Aggregate a turn
|
|
9
9
|
|
|
@@ -42,7 +42,7 @@ for await (const event of response) {
|
|
|
42
42
|
}
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
`message.appended` and `reasoning.appended` are incremental events.
|
|
45
|
+
`message.appended` and `reasoning.appended` are incremental delta events. Their completed forms, `message.completed` and `reasoning.completed`, are the compatibility path for clients that don't render deltas.
|
|
46
46
|
|
|
47
47
|
## Handle event types
|
|
48
48
|
|
|
@@ -117,21 +117,22 @@ for await (const event of session.stream({ startIndex: 0 })) {
|
|
|
117
117
|
|
|
118
118
|
## Abort a request
|
|
119
119
|
|
|
120
|
-
Pass an `AbortSignal` to cancel the POST or stream:
|
|
120
|
+
Pass an `AbortSignal` to cancel the POST or stream. Arm the timeout before awaiting `send()` so it covers the POST as well as the stream:
|
|
121
121
|
|
|
122
122
|
```ts
|
|
123
123
|
const controller = new AbortController();
|
|
124
|
+
const timeout = setTimeout(() => controller.abort(), 10_000);
|
|
124
125
|
|
|
125
126
|
const response = await session.send({
|
|
126
127
|
message: "Run a long analysis.",
|
|
127
128
|
signal: controller.signal,
|
|
128
129
|
});
|
|
129
130
|
|
|
130
|
-
setTimeout(() => controller.abort(), 10_000);
|
|
131
|
-
|
|
132
131
|
for await (const event of response) {
|
|
133
132
|
console.log(event.type);
|
|
134
133
|
}
|
|
134
|
+
|
|
135
|
+
clearTimeout(timeout);
|
|
135
136
|
```
|
|
136
137
|
|
|
137
138
|
Once a response is aborted, create a new send for the next turn. Don't reuse the same `MessageResponse`.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Deployment"
|
|
3
|
-
description: "A production checklist for shipping an Eve agent on Vercel
|
|
3
|
+
description: "A production checklist for shipping an Eve agent on Vercel, covering build output, env and secrets, sandbox backend, prewarm, auth, deploy, and verify."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Eve runs the same way locally and on Vercel, so taking an agent from `eve dev` to production is mostly mechanical. Work through this checklist in order.
|
|
7
7
|
|
|
8
8
|
## 1. Build
|
|
9
9
|
|
|
@@ -13,16 +13,16 @@ You've got an agent running under `eve dev` and now you want it live. Eve runs t
|
|
|
13
13
|
eve build
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
When `VERCEL` is set (every hosted Vercel build sets it), `eve build` writes the Vercel output bundle under `.vercel/output`. A plain local `eve build` skips that bundle. Either way you get Eve's compiled framework artifacts under `.eve/`, including the discovery manifest, compiled manifest, diagnostics, and module map. Open those to see which authored surface a deployment will load. For the artifact guide and what to do when `eve build` fails, see [Observability](./instrumentation).
|
|
17
17
|
|
|
18
|
-
## 2. Environment variables
|
|
18
|
+
## 2. Environment variables and secrets
|
|
19
19
|
|
|
20
20
|
Set these in your Vercel project's environment variables, never in source or compiled artifacts:
|
|
21
21
|
|
|
22
|
-
- **A model credential.**
|
|
23
|
-
- **Route-auth secrets**, for example `ROUTE_AUTH_BASIC_PASSWORD` and any JWT/OIDC signing keys referenced by your channel's `auth` (see [Auth
|
|
22
|
+
- **A model credential.** The lowest-setup option is the Vercel AI Gateway. Link a Vercel project, and gateway model ids like `anthropic/claude-opus-4.8` authenticate through Vercel OIDC, with no provider keys to manage. To call a provider directly instead, set its key (for example `OPENAI_API_KEY`).
|
|
23
|
+
- **Route-auth secrets**, for example `ROUTE_AUTH_BASIC_PASSWORD` and any JWT/OIDC signing keys referenced by your channel's `auth` (see [Auth and route protection](./auth-and-route-protection)).
|
|
24
24
|
|
|
25
|
-
Route-auth secrets never
|
|
25
|
+
Route-auth secrets are never serialized into the compiled discovery or module-map artifacts. The runtime re-materializes them from the authored channel definition instead. If your deployment sits behind Vercel preview protection and you want to drive it with `eve dev`, set `VERCEL_AUTOMATION_BYPASS_SECRET` locally before launching.
|
|
26
26
|
|
|
27
27
|
## 3. Sandbox backend
|
|
28
28
|
|
|
@@ -41,7 +41,7 @@ Leave `backend` off and Eve falls back to `defaultBackend()`, which picks the Ve
|
|
|
41
41
|
|
|
42
42
|
## 4. Build-time sandbox prewarm
|
|
43
43
|
|
|
44
|
-
During hosted builds, Eve prewarms reusable Vercel sandbox templates so the first session doesn't
|
|
44
|
+
During hosted builds, Eve prewarms reusable Vercel sandbox templates so the first session doesn't pay the cold-start cost:
|
|
45
45
|
|
|
46
46
|
- Prewarm runs only when both `VERCEL` and `VERCEL_DEPLOYMENT_ID` are present.
|
|
47
47
|
- A sandbox with no `bootstrap()` and no workspace seed files gets skipped.
|
|
@@ -53,7 +53,7 @@ During hosted builds, Eve prewarms reusable Vercel sandbox templates so the firs
|
|
|
53
53
|
|
|
54
54
|
## 5. Auth
|
|
55
55
|
|
|
56
|
-
Swap any scaffolded `placeholderAuth()` for your real policy before the first production browser request hits the app. Both the framework default and the placeholder reject production browser traffic, so an unconfigured app fails closed rather than serving open routes. See [Auth
|
|
56
|
+
Swap any scaffolded `placeholderAuth()` for your real policy before the first production browser request hits the app. Both the framework default and the placeholder reject production browser traffic, so an unconfigured app fails closed rather than serving open routes. See [Auth and route protection](./auth-and-route-protection) for the ordered auth walk and the fail-closed guarantee.
|
|
57
57
|
|
|
58
58
|
## 6. Deploy on Vercel
|
|
59
59
|
|
|
@@ -65,10 +65,6 @@ vercel deploy
|
|
|
65
65
|
|
|
66
66
|
The deployed app serves the same stable health, session, and stream routes you've been hitting locally.
|
|
67
67
|
|
|
68
|
-
## How Eve sits behind a host framework
|
|
69
|
-
|
|
70
|
-
You can deploy an Eve app on its own, or mount it inside a host web framework that owns the rest of the site (marketing pages, a dashboard, other API routes). The host keeps its own routing and serves Eve's routes through the framework integration. For mounting Eve in Next.js (`withEve`) and the other supported frameworks, see [Frontend](./frontend/nextjs). Either way, the agent surface and HTTP contract are identical.
|
|
71
|
-
|
|
72
68
|
## 7. Verify the deployment
|
|
73
69
|
|
|
74
70
|
Smoke-test the live routes. Health first:
|
|
@@ -85,13 +81,13 @@ curl -X POST https://<your-app>/eve/v1/session \
|
|
|
85
81
|
-d '{"message":"Hello from production"}'
|
|
86
82
|
```
|
|
87
83
|
|
|
88
|
-
Attach to
|
|
84
|
+
The POST returns a JSON body whose `sessionId` identifies the new session. Attach to that session's stream with it:
|
|
89
85
|
|
|
90
86
|
```bash
|
|
91
87
|
curl https://<your-app>/eve/v1/session/<sessionId>/stream
|
|
92
88
|
```
|
|
93
89
|
|
|
94
|
-
Or
|
|
90
|
+
Or drive the deployment interactively with the dev TUI, which is handy for preview and production smoke tests:
|
|
95
91
|
|
|
96
92
|
```bash
|
|
97
93
|
eve dev https://<your-app>
|
|
@@ -103,20 +99,26 @@ eve dev https://<your-app>
|
|
|
103
99
|
|
|
104
100
|
Once the agent is deployed, the platform auto-detects `eve` as the framework and surfaces an **Agent Runs** tab under your project's **Observability** view in the Vercel dashboard. From there you can browse sessions and drill into each conversation's trace.
|
|
105
101
|
|
|
106
|
-
> The Agent Runs tab is currently gated
|
|
102
|
+
> The Agent Runs tab is currently gated. Your Vercel team needs the feature enabled before it appears. If you don't see it, reach out to your Vercel contact to get your team enabled.
|
|
103
|
+
|
|
104
|
+
Agent Runs is separate from the OpenTelemetry exporters configured in [Observability](./instrumentation). Those still work and are the recommended path if you want spans in Braintrust, Datadog, or another third-party backend.
|
|
105
|
+
|
|
106
|
+
## How Eve sits behind a host framework
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
You can deploy an Eve app on its own, or mount it inside a host web framework that owns the rest of the site (marketing pages, a dashboard, other API routes). The host keeps its own routing and serves Eve's routes through the framework integration. Either way, the agent surface and HTTP contract are identical. For mounting Eve in Next.js (`withEve`) and the other supported frameworks, see [Frontend](./frontend/nextjs).
|
|
109
109
|
|
|
110
110
|
## Checklist
|
|
111
111
|
|
|
112
|
-
- [ ] `eve build` succeeds and writes `.vercel/output
|
|
112
|
+
- [ ] `eve build` succeeds, and writes `.vercel/output` when `VERCEL` is set.
|
|
113
113
|
- [ ] Provider keys and route-auth secrets are set in Vercel env vars.
|
|
114
114
|
- [ ] The sandbox backend matches the environment (`vercel()` or `defaultBackend()`).
|
|
115
115
|
- [ ] Build-time prewarm reused or built templates without failing.
|
|
116
116
|
- [ ] `placeholderAuth()` is replaced with your real policy.
|
|
117
|
+
- [ ] `vercel deploy` succeeds.
|
|
118
|
+
- [ ] The health, session, and stream routes respond on the deployment URL.
|
|
117
119
|
|
|
118
120
|
## What to read next
|
|
119
121
|
|
|
120
|
-
- [Auth
|
|
121
|
-
- [
|
|
122
|
+
- [Auth and route protection](./auth-and-route-protection): secure the routes you deployed
|
|
123
|
+
- [Observability](./instrumentation): tracing, run tags, and common failures
|
|
122
124
|
- [Sandbox](../sandbox): backends, lifecycle, and credential brokering
|