eve 0.13.8 → 0.14.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 +16 -0
- package/dist/src/channel/routes.d.ts +5 -0
- package/dist/src/channel/send.js +1 -1
- package/dist/src/channel/types.d.ts +5 -0
- package/dist/src/compiled/.vendor-stamp.json +12 -8
- package/dist/src/compiled/@ai-sdk/anthropic/index.d.ts +2 -2
- package/dist/src/compiled/@ai-sdk/anthropic/index.js +2 -2
- package/dist/src/compiled/@ai-sdk/google/index.d.ts +25 -3
- package/dist/src/compiled/@ai-sdk/google/index.js +6 -6
- package/dist/src/compiled/@ai-sdk/mcp/index.d.ts +647 -30
- package/dist/src/compiled/@ai-sdk/mcp/index.js +1 -1
- package/dist/src/compiled/@ai-sdk/openai/index.d.ts +8 -2
- package/dist/src/compiled/@ai-sdk/openai/index.js +2 -2
- package/dist/src/compiled/@ai-sdk/otel/index.d.ts +165 -28
- package/dist/src/compiled/@ai-sdk/otel/index.js +3 -3
- package/dist/src/compiled/@ai-sdk/provider/index.d.ts +10 -2
- package/dist/src/compiled/@ai-sdk/provider-utils/index.d.ts +2362 -0
- package/dist/src/compiled/@ai-sdk/provider-utils/index.js +1 -0
- package/dist/src/compiled/@workflow/serde/LICENSE.md +3 -0
- package/dist/src/compiled/@workflow/serde/index.d.ts +30 -0
- package/dist/src/compiled/@workflow/serde/index.js +1 -0
- package/dist/src/compiled/_chunks/workflow/{dist-C9PV_vnE.js → dist-D7CzPkf8.js} +1 -1
- package/dist/src/compiled/eventsource-parser/stream/LICENSE +21 -0
- package/dist/src/compiled/eventsource-parser/stream/index.d.ts +121 -0
- package/dist/src/compiled/eventsource-parser/stream/index.js +1 -0
- package/dist/src/compiled/experimental-ai-sdk-code-mode/approval-continuation.d.ts +7 -7
- package/dist/src/compiled/experimental-ai-sdk-code-mode/continuation-capability.d.ts +15 -4
- package/dist/src/compiled/experimental-ai-sdk-code-mode/index.d.ts +1 -1
- package/dist/src/compiled/experimental-ai-sdk-code-mode/index.js +15 -15
- package/dist/src/compiled/experimental-ai-sdk-code-mode/interrupt-continuation.d.ts +5 -5
- package/dist/src/compiled/experimental-ai-sdk-code-mode/runtime/protocol.d.ts +13 -2
- package/dist/src/compiled/experimental-ai-sdk-code-mode/types.d.ts +26 -0
- package/dist/src/compiled/json-schema/LICENSE +21 -0
- package/dist/src/compiled/json-schema/index.d.ts +749 -0
- package/dist/src/compiled/json-schema/index.js +1 -0
- package/dist/src/compiler/manifest.js +1 -1
- package/dist/src/compiler/normalize-agent-config.js +1 -1
- package/dist/src/context/build-dynamic-tools.js +1 -1
- package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
- package/dist/src/context/keys.d.ts +1 -1
- package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
- package/dist/src/execution/dispatch-workflow-runtime-actions-step.d.ts +12 -0
- package/dist/src/execution/dispatch-workflow-runtime-actions-step.js +1 -0
- package/dist/src/execution/next-driver-action.d.ts +1 -1
- package/dist/src/execution/node-step.js +1 -1
- package/dist/src/execution/session.js +3 -3
- package/dist/src/execution/turn-workflow.js +1 -1
- package/dist/src/execution/workflow-entry.js +1 -1
- package/dist/src/execution/workflow-runtime.d.ts +2 -11
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/execution/workflow-steps.d.ts +1 -1
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/harness/action-result-helpers.d.ts +2 -2
- package/dist/src/harness/emission.js +1 -1
- package/dist/src/harness/execute-tool.d.ts +2 -2
- package/dist/src/harness/input-extraction.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/harness/tools.d.ts +4 -6
- package/dist/src/harness/tools.js +1 -1
- package/dist/src/harness/types.d.ts +4 -10
- package/dist/src/harness/workflow-continuation-security.d.ts +4 -0
- package/dist/src/harness/workflow-continuation-security.js +1 -0
- package/dist/src/harness/workflow-interrupt-state.d.ts +14 -0
- package/dist/src/harness/workflow-interrupt-state.js +1 -0
- package/dist/src/harness/workflow-lifecycle.d.ts +13 -0
- package/dist/src/harness/workflow-lifecycle.js +1 -0
- package/dist/src/harness/workflow-runtime-action-state.d.ts +9 -0
- package/dist/src/harness/workflow-runtime-action-state.js +1 -0
- package/dist/src/harness/workflow-sandbox.d.ts +22 -0
- package/dist/src/harness/workflow-sandbox.js +2 -0
- package/dist/src/harness/workflow-tool-description.d.ts +2 -2
- package/dist/src/harness/workflow-tool-description.js +16 -4
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/authored-definition/connection.js +1 -1
- package/dist/src/internal/authored-definition/core.js +1 -1
- package/dist/src/internal/authored-definition/schema-backed.js +1 -1
- package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
- package/dist/src/internal/nitro/host/workflow-sandbox-runtime-plugin.d.ts +1 -0
- package/dist/src/internal/nitro/host/workflow-sandbox-runtime-plugin.js +1 -0
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response-from-manifest.js +1 -1
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.js +1 -1
- package/dist/src/internal/workflow/runtime.d.ts +1 -0
- package/dist/src/public/channels/slack/attachments.js +1 -1
- package/dist/src/public/channels/slack/auth.d.ts +2 -0
- package/dist/src/public/channels/slack/auth.js +1 -1
- package/dist/src/public/channels/slack/defaults.js +2 -2
- package/dist/src/public/channels/slack/inbound.d.ts +4 -11
- package/dist/src/public/channels/slack/inbound.js +1 -2
- package/dist/src/public/channels/slack/model-context.d.ts +28 -0
- package/dist/src/public/channels/slack/model-context.js +3 -0
- package/dist/src/public/channels/slack/slackChannel.d.ts +8 -0
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/public/connections/index.d.ts +1 -1
- package/dist/src/public/definitions/agent.d.ts +1 -1
- package/dist/src/public/definitions/approval.d.ts +40 -0
- package/dist/src/public/definitions/approval.js +1 -0
- package/dist/src/public/definitions/connections/mcp.d.ts +11 -9
- package/dist/src/public/definitions/connections/mcp.js +1 -1
- package/dist/src/public/definitions/connections/openapi.d.ts +9 -7
- package/dist/src/public/definitions/connections/openapi.js +1 -1
- package/dist/src/public/definitions/tool.d.ts +7 -20
- package/dist/src/public/index.d.ts +1 -1
- package/dist/src/public/tools/approval/approval-helpers.d.ts +7 -7
- package/dist/src/public/tools/approval/approval-helpers.js +1 -1
- package/dist/src/public/tools/approval/index.d.ts +1 -1
- package/dist/src/public/tools/index.d.ts +2 -1
- package/dist/src/public/tools/internal.js +1 -1
- package/dist/src/runtime/agent/bootstrap.d.ts +1 -0
- package/dist/src/runtime/agent/bootstrap.js +1 -1
- package/dist/src/runtime/agent/mock-model-adapter.js +2 -3
- package/dist/src/runtime/connections/mcp-client.d.ts +3 -3
- package/dist/src/runtime/connections/mcp-client.js +1 -1
- package/dist/src/runtime/connections/registry.d.ts +2 -2
- package/dist/src/runtime/connections/resolve-authorization.d.ts +11 -0
- package/dist/src/runtime/connections/resolve-authorization.js +1 -0
- package/dist/src/runtime/connections/types.d.ts +27 -11
- package/dist/src/runtime/framework-tools/connection-search-dynamic.js +1 -1
- package/dist/src/runtime/resolve-agent-graph.js +1 -1
- package/dist/src/runtime/resolve-agent.js +1 -1
- package/dist/src/runtime/resolve-connection.js +1 -1
- package/dist/src/runtime/resolve-tool.d.ts +1 -1
- package/dist/src/runtime/resolve-tool.js +1 -1
- package/dist/src/runtime/types.d.ts +8 -7
- package/dist/src/setup/primitives/pm/pnpm.js +6 -5
- package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +2 -2
- package/dist/src/setup/scaffold/update/channels.js +1 -1
- package/dist/src/shared/agent-definition.d.ts +11 -13
- package/dist/src/shared/dynamic-tool-definition.d.ts +3 -3
- package/dist/src/shared/tool-definition.d.ts +1 -2
- package/dist/src/shared/workflow-sandbox.d.ts +37 -0
- package/dist/src/shared/workflow-sandbox.js +1 -0
- package/docs/agent-config.md +30 -10
- package/docs/channels/custom.mdx +2 -2
- package/docs/channels/slack.mdx +7 -13
- package/docs/connections/mcp.mdx +2 -2
- package/docs/connections/openapi.mdx +37 -2
- package/docs/connections/overview.mdx +32 -0
- package/docs/guides/deployment.md +2 -2
- package/docs/guides/dynamic-workflows.md +1 -7
- package/docs/guides/frontend/overview.mdx +1 -1
- package/docs/guides/frontend/use-eve-agent-svelte.mdx +1 -1
- package/docs/guides/frontend/use-eve-agent-vue.mdx +1 -1
- package/docs/guides/session-context.md +2 -1
- package/docs/reference/typescript-api.md +2 -2
- package/docs/subagents.mdx +2 -2
- package/docs/tools/human-in-the-loop.md +43 -6
- package/docs/tools/overview.mdx +3 -3
- package/docs/tutorial/first-agent.mdx +1 -1
- package/docs/tutorial/guard-the-spend.mdx +4 -3
- package/docs/tutorial/ship-it.mdx +1 -1
- package/package.json +14 -11
- package/dist/src/compiled/@ai-sdk/anthropic/_provider-utils.d.ts +0 -15
- package/dist/src/compiled/@ai-sdk/google/_provider-utils.d.ts +0 -11
- package/dist/src/compiled/@ai-sdk/openai/_provider-utils.d.ts +0 -15
- package/dist/src/compiled/@ai-sdk/provider/_json-schema.d.ts +0 -5
- package/dist/src/execution/dispatch-code-mode-runtime-actions-step.d.ts +0 -21
- package/dist/src/execution/dispatch-code-mode-runtime-actions-step.js +0 -1
- package/dist/src/harness/code-mode-interrupt-state.d.ts +0 -26
- package/dist/src/harness/code-mode-interrupt-state.js +0 -1
- package/dist/src/harness/code-mode-lifecycle.d.ts +0 -16
- package/dist/src/harness/code-mode-lifecycle.js +0 -1
- package/dist/src/harness/code-mode-runtime-action-state.d.ts +0 -6
- package/dist/src/harness/code-mode-runtime-action-state.js +0 -1
- package/dist/src/harness/code-mode.d.ts +0 -26
- package/dist/src/harness/code-mode.js +0 -1
- package/dist/src/harness/sandbox-surface.d.ts +0 -68
- package/dist/src/harness/sandbox-surface.js +0 -1
- package/dist/src/internal/nitro/host/code-mode-runtime-dependency-plugin.d.ts +0 -1
- package/dist/src/internal/nitro/host/code-mode-runtime-dependency-plugin.js +0 -1
- package/dist/src/runtime/framework-tools/code-mode-connection-auth.d.ts +0 -29
- package/dist/src/runtime/framework-tools/code-mode-connection-auth.js +0 -1
- package/dist/src/shared/code-mode.d.ts +0 -29
- package/dist/src/shared/code-mode.js +0 -1
package/docs/agent-config.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "agent.ts"
|
|
3
|
-
description: "Set the agent's runtime config in agent.ts with defineAgent, including the model and compaction."
|
|
3
|
+
description: "Set the agent's runtime config in agent.ts with defineAgent, including the model, reasoning effort, and compaction."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
An agent's `agent.ts` calls `defineAgent` (from `eve`) to set its runtime config.
|
|
@@ -33,12 +33,33 @@ import { anthropic } from "@ai-sdk/anthropic";
|
|
|
33
33
|
import { defineAgent } from "eve";
|
|
34
34
|
|
|
35
35
|
export default defineAgent({
|
|
36
|
-
model: anthropic("claude-opus-4
|
|
36
|
+
model: anthropic("claude-opus-4-8"),
|
|
37
37
|
});
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
+
Direct provider model ids use the provider's native format. For Anthropic, the
|
|
41
|
+
version uses hyphens (`claude-opus-4-8`), while the Gateway id above uses a dot
|
|
42
|
+
(`anthropic/claude-opus-4.8`).
|
|
43
|
+
|
|
40
44
|
Model use is subject to the terms, data-processing commitments, retention behavior, and available controls of the selected provider and routing path. Review the [AI Gateway model catalog](https://vercel.com/ai-gateway/models) for gateway-routed models, and review the provider's terms when you configure a direct `LanguageModel`.
|
|
41
45
|
|
|
46
|
+
## Reasoning effort
|
|
47
|
+
|
|
48
|
+
Set `reasoning` to control the model's reasoning effort through AI SDK's
|
|
49
|
+
provider-agnostic option:
|
|
50
|
+
|
|
51
|
+
```ts title="agent/agent.ts"
|
|
52
|
+
export default defineAgent({
|
|
53
|
+
model: "openai/gpt-5.5",
|
|
54
|
+
reasoning: "high",
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Supported values are `"provider-default"`, `"none"`, `"minimal"`, `"low"`,
|
|
59
|
+
`"medium"`, `"high"`, and `"xhigh"`. The selected model and provider determine
|
|
60
|
+
which levels are available and how they map to provider-native settings. Use
|
|
61
|
+
`modelOptions.providerOptions` when you need provider-specific reasoning controls.
|
|
62
|
+
|
|
42
63
|
## Compaction
|
|
43
64
|
|
|
44
65
|
Compaction summarizes older turns as you approach the context window. It's on by default, so you only tune when it kicks in. Lower `thresholdPercent` to compact sooner:
|
|
@@ -85,14 +106,13 @@ external in hosted output, list it in `build.externalDependencies`.
|
|
|
85
106
|
|
|
86
107
|
`defineAgent` takes a few more fields, all optional. For the exported types, see the [TypeScript API](./reference/typescript-api).
|
|
87
108
|
|
|
88
|
-
| Field | Type
|
|
89
|
-
| -------------- |
|
|
90
|
-
| `
|
|
91
|
-
| `
|
|
92
|
-
| `
|
|
93
|
-
| `
|
|
94
|
-
|
|
95
|
-
`codeMode` is experimental and may change or be removed.
|
|
109
|
+
| Field | Type | Default | Description |
|
|
110
|
+
| -------------- | --------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
111
|
+
| `reasoning` | `AgentReasoningDefinition` | provider default | Provider-agnostic reasoning effort forwarded to the agent's turn model calls. |
|
|
112
|
+
| `modelOptions` | `AgentModelOptionsDefinition` | none | Provider option overrides forwarded to the model call. |
|
|
113
|
+
| `experimental` | `{ workflow?: { world?: string } }` | unset | Opt-in settings that can change or disappear in any release. Treat them as unstable. `workflow.world` selects the Workflow world package backing session state, queues, hooks, and streams on the root agent. |
|
|
114
|
+
| `outputSchema` | Standard Schema or a JSON Schema object | none | Structured return type for task-mode runs (a subagent, schedule, or remote job). Interactive conversation turns ignore it unless the client supplies a per-message schema. |
|
|
115
|
+
| `build` | `{ externalDependencies?: string[] }` | none | Hosted-build packaging controls. `externalDependencies` keeps listed packages external while eve compiles authored modules such as tools and channels, and traces those packages into the hosted output. |
|
|
96
116
|
|
|
97
117
|
`externalDependencies` is a packaging control only. It keeps selected packages as runtime dependencies in the hosted output; it does not authorize, configure, or review any third-party service those packages may call.
|
|
98
118
|
|
package/docs/channels/custom.mdx
CHANGED
|
@@ -46,7 +46,7 @@ export default defineChannel({
|
|
|
46
46
|
|
|
47
47
|
Declare routes with the `POST()` and `GET()` helpers. Each route handler receives the raw `Request` and a helpers object:
|
|
48
48
|
|
|
49
|
-
- `send(message, { auth, continuationToken, state? })` starts or resumes a session. Returns a `Session`.
|
|
49
|
+
- `send(message, { auth, continuationToken, state?, title? })` starts or resumes a session. `title` overrides the new workflow session's display title without changing the model message. Returns a `Session`.
|
|
50
50
|
- `getSession(sessionId)` looks up an existing session. The returned `Session` exposes `getEventStream({ startIndex? })` for streaming.
|
|
51
51
|
- `receive(channel, ...)` hands inbound work to a different channel for cross-channel hand-off.
|
|
52
52
|
- `params` holds route parameters extracted from the path pattern.
|
|
@@ -182,7 +182,7 @@ When a parent agent dispatches a subagent, the framework forwards the parent's c
|
|
|
182
182
|
|
|
183
183
|
## Continuation tokens
|
|
184
184
|
|
|
185
|
-
Each call to `send(message, { auth, continuationToken, state? })` from a channel route addresses a session by its channel-local raw token. The framework prepends the channel name, derived from the file stem under `agent/channels/`, before handing the token to the runtime.
|
|
185
|
+
Each call to `send(message, { auth, continuationToken, state?, title? })` from a channel route addresses a session by its channel-local raw token. The framework prepends the channel name, derived from the file stem under `agent/channels/`, before handing the token to the runtime.
|
|
186
186
|
|
|
187
187
|
```ts
|
|
188
188
|
import { slackContinuationToken } from "eve/channels/slack";
|
package/docs/channels/slack.mdx
CHANGED
|
@@ -54,28 +54,22 @@ Inbound hooks decide whether to dispatch a turn and with what `auth`. Return `{
|
|
|
54
54
|
- `onDirectMessage(ctx, message)` handles `message.im` events (needs `im:history` scope). Bot-authored messages and edits are filtered out first.
|
|
55
55
|
- `onInteraction(action, ctx)` handles `block_actions` callbacks not consumed by HITL.
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
eve attaches the triggering Slack user id to the same model message as the message text. This keeps speaker attribution intact when several people use one thread without making profile lookup requests.
|
|
58
|
+
|
|
59
|
+
You get the triggering mention by default, but not the earlier replies in the thread. Enable `threadContext` to fetch and inject them with every message attributed by stable Slack user id. Use `since: "last-agent-reply"` so repeated mentions inject only what is new:
|
|
58
60
|
|
|
59
61
|
```ts
|
|
60
|
-
import {
|
|
62
|
+
import { slackChannel } from "eve/channels/slack";
|
|
61
63
|
import { connectSlackCredentials } from "@vercel/connect/eve";
|
|
62
64
|
|
|
63
65
|
export default slackChannel({
|
|
64
66
|
credentials: connectSlackCredentials("slack/my-agent"),
|
|
65
|
-
|
|
66
|
-
const auth = defaultSlackAuth(message, ctx);
|
|
67
|
-
const prior = await loadThreadContextMessages(ctx.thread, message, {
|
|
68
|
-
since: "last-agent-reply",
|
|
69
|
-
});
|
|
70
|
-
if (prior.length === 0) return { auth };
|
|
71
|
-
const transcript = prior
|
|
72
|
-
.map((m) => `${m.isMe ? "you" : (m.user ?? "user")}: ${m.markdown}`)
|
|
73
|
-
.join("\n");
|
|
74
|
-
return { auth, context: [`Recent thread messages since your last reply:\n\n${transcript}`] };
|
|
75
|
-
},
|
|
67
|
+
threadContext: { since: "last-agent-reply" },
|
|
76
68
|
});
|
|
77
69
|
```
|
|
78
70
|
|
|
71
|
+
`threadContext` performs one `conversations.replies` request for each triggering thread reply and requires the matching Slack history scope. Omit it when the agent should see only direct mentions. `loadThreadContextMessages` remains available when you need custom filtering or non-model processing of the raw thread messages.
|
|
72
|
+
|
|
79
73
|
### Delivery
|
|
80
74
|
|
|
81
75
|
The default handlers reply in-thread and show progress. Typing indicators post automatically: `Thinking…` on inbound, `Working…` on `turn.started`, a truncated reasoning snippet on `reasoning.appended`, and tool status on `actions.requested`. Reasoning snippets build progressively: extensions of at least four characters appear immediately, while smaller streamed deltas use the five-second refresh interval to avoid one Slack request per token. Override `events["reasoning.appended"]` if you prefer generic wording. Override `onAppMention` or the `events` handlers to customize.
|
package/docs/connections/mcp.mdx
CHANGED
|
@@ -48,8 +48,8 @@ Use `allow` for the smallest safe surface, especially on MCP servers that expose
|
|
|
48
48
|
|
|
49
49
|
MCP connections support the shared connection options:
|
|
50
50
|
|
|
51
|
-
- `auth` for static tokens, Vercel Connect,
|
|
52
|
-
- `headers` for API-key schemes
|
|
51
|
+
- `auth` for static tokens, Vercel Connect, self-hosted interactive OAuth, or a per-caller provider resolver.
|
|
52
|
+
- `headers` for static or per-caller API-key schemes and extra server configuration.
|
|
53
53
|
- `approval` for human-in-the-loop gates before connection tools run.
|
|
54
54
|
|
|
55
55
|
See [Connections](/docs/connections) for the shared auth, headers, and approval shapes.
|
|
@@ -34,6 +34,41 @@ OpenAPI connections use the shared connection fields from [Connections](/docs/co
|
|
|
34
34
|
|
|
35
35
|
Use `baseUrl` when the spec's `servers` list is absent, points at the wrong environment, or needs to be pinned for this agent.
|
|
36
36
|
|
|
37
|
+
## Path parameters
|
|
38
|
+
|
|
39
|
+
When an operation path contains dynamic segments, declare each segment as an OpenAPI path parameter. eve exposes path, query, header, and cookie parameters as top-level tool inputs, then substitutes `in: "path"` values into the matching `{name}` placeholder before making the request.
|
|
40
|
+
|
|
41
|
+
```ts title="agent/connections/cart.ts"
|
|
42
|
+
import { defineOpenAPIConnection } from "eve/connections";
|
|
43
|
+
|
|
44
|
+
export default defineOpenAPIConnection({
|
|
45
|
+
baseUrl: "https://api.example.com",
|
|
46
|
+
description: "Cart and checkout API.",
|
|
47
|
+
spec: {
|
|
48
|
+
openapi: "3.0.3",
|
|
49
|
+
info: { title: "Cart API", version: "1.0.0" },
|
|
50
|
+
paths: {
|
|
51
|
+
"/api/{dynamicsegment}/somethingelse": {
|
|
52
|
+
get: {
|
|
53
|
+
operationId: "getSomethingElse",
|
|
54
|
+
parameters: [
|
|
55
|
+
{
|
|
56
|
+
name: "dynamicsegment",
|
|
57
|
+
in: "path",
|
|
58
|
+
required: true,
|
|
59
|
+
schema: { type: "string" },
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
responses: { "200": { description: "OK" } },
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The parameter `name` must exactly match the placeholder inside the path. If the spec omits the `in: "path"` parameter, the generated tool has no input for that segment and eve cannot fill it in from query parameters.
|
|
71
|
+
|
|
37
72
|
## Operation filters
|
|
38
73
|
|
|
39
74
|
To narrow which generated tools the model sees, set exactly one of `operations.allow` or `operations.block`:
|
|
@@ -55,8 +90,8 @@ Filters match `operationId`. If an operation does not declare one, use the deter
|
|
|
55
90
|
|
|
56
91
|
OpenAPI connections support the shared connection options:
|
|
57
92
|
|
|
58
|
-
- `auth` for static tokens, Vercel Connect,
|
|
59
|
-
- `headers` for API-key schemes
|
|
93
|
+
- `auth` for static tokens, Vercel Connect, self-hosted interactive OAuth, or a per-caller provider resolver.
|
|
94
|
+
- `headers` for static or per-caller API-key schemes and extra server configuration.
|
|
60
95
|
- `approval` for human-in-the-loop gates before generated operation tools run.
|
|
61
96
|
|
|
62
97
|
See [Connections](/docs/connections) for the shared auth, headers, and approval shapes.
|
|
@@ -57,6 +57,38 @@ export default defineMcpClientConnection({
|
|
|
57
57
|
});
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
+
## Per-caller auth and headers
|
|
61
|
+
|
|
62
|
+
When credentials or routing depend on the caller, make `auth` or `headers` a function. eve calls it inside the active turn and passes the same session context exposed to tools and hooks:
|
|
63
|
+
|
|
64
|
+
```ts title="agent/connections/warehouse.ts"
|
|
65
|
+
import { defineOpenAPIConnection } from "eve/connections";
|
|
66
|
+
|
|
67
|
+
export default defineOpenAPIConnection({
|
|
68
|
+
spec: "https://warehouse.example.com/openapi.json",
|
|
69
|
+
description: "The caller's tenant-scoped warehouse.",
|
|
70
|
+
auth: (ctx) => ({
|
|
71
|
+
principalType: "user",
|
|
72
|
+
getToken: async () => ({
|
|
73
|
+
token: await tenantToken(ctx.session.auth.current),
|
|
74
|
+
}),
|
|
75
|
+
}),
|
|
76
|
+
headers: (ctx) => ({
|
|
77
|
+
"X-Tenant-Id": tenantId(ctx.session.auth.current),
|
|
78
|
+
}),
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
An `auth` resolver returns the same provider object accepted by static `auth`, including a `connect(...)` provider for interactive OAuth. The resolver itself can be async. Header callbacks can return the whole map, as above, or resolve individual values:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
headers: {
|
|
86
|
+
"X-Tenant-Id": (ctx) => tenantId(ctx.session.auth.current),
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Use `principalType: "user"` for per-user tokens so eve rejects unauthenticated callers and keys its step-local token cache by user. The resolver supplements route auth; it does not authenticate the inbound request. Static auth objects and header maps remain available when every caller shares the same configuration.
|
|
91
|
+
|
|
60
92
|
## Per-connection approval
|
|
61
93
|
|
|
62
94
|
To put every tool a connection serves behind a human, use the helpers from `eve/tools/approval`:
|
|
@@ -74,11 +74,11 @@ import { anthropic } from "@ai-sdk/anthropic";
|
|
|
74
74
|
import { defineAgent } from "eve";
|
|
75
75
|
|
|
76
76
|
export default defineAgent({
|
|
77
|
-
model: anthropic("claude-opus-4
|
|
77
|
+
model: anthropic("claude-opus-4-8"),
|
|
78
78
|
});
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
With that shape, the model call goes directly to Anthropic and the runtime reads `ANTHROPIC_API_KEY`. The same pattern works for OpenAI after installing `@ai-sdk/openai`, using `openai("...")`, and setting `OPENAI_API_KEY`. This is the usual choice when self-deploying without any Vercel-managed services.
|
|
81
|
+
With that shape, the model call goes directly to Anthropic and the runtime reads `ANTHROPIC_API_KEY`. Direct Anthropic model ids use hyphens (`claude-opus-4-8`), unlike the dotted Gateway id (`anthropic/claude-opus-4.8`). The same pattern works for OpenAI after installing `@ai-sdk/openai`, using `openai("...")`, and setting `OPENAI_API_KEY`. This is the usual choice when self-deploying without any Vercel-managed services.
|
|
82
82
|
|
|
83
83
|
## 4. Sandbox backend
|
|
84
84
|
|
|
@@ -3,7 +3,7 @@ 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. 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.
|
|
6
|
+
The experimental `Workflow` tool lets the model write JavaScript that coordinates the agent's own subagents as a single durable step. The program can run them in sequence, feed one result into the next, fan out over a list, and combine the results. You enable the capability and the model decides and runs the orchestration.
|
|
7
7
|
|
|
8
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
|
|
|
@@ -63,12 +63,6 @@ That is an allowlist, not a denylist. The sandbox cannot read files, open a sock
|
|
|
63
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.
|
|
64
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.
|
|
65
65
|
|
|
66
|
-
## Relationship to code mode
|
|
67
|
-
|
|
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.
|
|
71
|
-
|
|
72
66
|
## What to read next
|
|
73
67
|
|
|
74
68
|
- Declare the subagents a workflow orchestrates → [Subagents](../subagents)
|
|
@@ -100,7 +100,7 @@ Assistant text, reasoning, tool calls, and tool results stream into `data` as th
|
|
|
100
100
|
|
|
101
101
|
## Human-in-the-loop prompts
|
|
102
102
|
|
|
103
|
-
Tools opt into approval with `
|
|
103
|
+
Tools opt into approval with `approval`, and the model can also ask a question with `ask_question` — see [Human-in-the-loop](/docs/human-in-the-loop) for the server-side model. Either way the stream emits an `input.requested` event, and the pending request rides on a `dynamic-tool` part of the latest message at `part.toolMetadata?.eve?.inputRequest`. Read it, then answer through the same session with `send()`:
|
|
104
104
|
|
|
105
105
|
```tsx
|
|
106
106
|
const request = agent.data.messages
|
|
@@ -78,7 +78,7 @@ await agent.send({
|
|
|
78
78
|
|
|
79
79
|
## Human-in-the-loop prompts
|
|
80
80
|
|
|
81
|
-
A tool opts into approval with `
|
|
81
|
+
A tool opts into approval with `approval` ([Tools](../../tools)). When one fires, the pending request rides along on a `dynamic-tool` part of the latest message at `part.toolMetadata?.eve?.inputRequest`. Read it, then answer through the same session with `agent.send({ inputResponses })`:
|
|
82
82
|
|
|
83
83
|
```ts
|
|
84
84
|
import type { EveDynamicToolPart, EveMessagePart } from "eve/svelte";
|
|
@@ -89,7 +89,7 @@ async function onFileChange(event: Event) {
|
|
|
89
89
|
|
|
90
90
|
## Human-in-the-loop prompts
|
|
91
91
|
|
|
92
|
-
A tool opts into approval with `
|
|
92
|
+
A tool opts into approval with `approval` ([Tools](../../tools)). When it triggers, the pending request shows up as a `dynamic-tool` part on the latest message at `part.toolMetadata?.eve?.inputRequest`. Read it, then answer through the same session with `send({ inputResponses })`:
|
|
93
93
|
|
|
94
94
|
```ts
|
|
95
95
|
import type { EveDynamicToolPart, EveMessagePart } from "eve/vue";
|
|
@@ -3,7 +3,7 @@ title: "Session Context"
|
|
|
3
3
|
description: "Runtime helpers: ctx.session, ctx.getSandbox, ctx.getSkill, and defineState."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
eve exposes runtime state through the `ctx` parameter passed to tool `execute`, hook handlers,
|
|
6
|
+
eve exposes runtime state through the `ctx` parameter passed to tool `execute`, hook handlers, channel event handlers, and connection auth/header resolvers:
|
|
7
7
|
|
|
8
8
|
- `ctx.session`: session metadata, turn, auth, and parent lineage
|
|
9
9
|
- `ctx.getSandbox()`: live sandbox handle for the current agent
|
|
@@ -119,6 +119,7 @@ export const budget = defineState<BudgetState>("myapp.budget", () => ({
|
|
|
119
119
|
Safe places:
|
|
120
120
|
|
|
121
121
|
- inside `defineTool(...).execute(input, ctx)`
|
|
122
|
+
- inside connection `auth: (ctx) => provider` and `headers: (ctx) => values` resolvers
|
|
122
123
|
- inside authored callbacks eve runs inside the runtime
|
|
123
124
|
- after asynchronous boundaries inside the same authored execution chain
|
|
124
125
|
|
|
@@ -51,11 +51,11 @@ export default defineTool({
|
|
|
51
51
|
| `defineEvalConfig` | `eve/evals` | `evals/evals.config.ts` | [Evals](../evals/overview) |
|
|
52
52
|
| `useEveAgent` | `eve/react`, `eve/vue`, `eve/svelte` | frontend | [Frontend](../guides/frontend/overview) |
|
|
53
53
|
|
|
54
|
-
A few non-`define*` helpers round out the set: `disableTool` and `ExperimentalWorkflow` from `eve/tools` (see [Default harness](../concepts/default-harness)), the route verbs `GET`/`POST`/`PUT`/`PATCH`/`DELETE`/`WS` from `eve/channels`, the approval
|
|
54
|
+
A few non-`define*` helpers round out the set: `disableTool` and `ExperimentalWorkflow` from `eve/tools` (see [Default harness](../concepts/default-harness)), the route verbs `GET`/`POST`/`PUT`/`PATCH`/`DELETE`/`WS` from `eve/channels`, the approval policies `always`/`once`/`never` from `eve/tools/approval`, and the channel auth helpers `localDev`/`vercelOidc`/`placeholderAuth` from `eve/channels/auth`. To wrap a built-in tool, import its default value from `eve/tools/defaults` (`bash`, `readFile`, `writeFile`, `glob`, `grep`, `webFetch`, `webSearch`, `todo`, `loadSkill`). `AgentReasoningDefinition` is exported from `eve` for the top-level `defineAgent({ reasoning })` setting. `AgentWorkflowDefinition` and `AgentWorkflowWorldDefinition` are exported from `eve` for the `defineAgent({ experimental: { workflow } })` config shape.
|
|
55
55
|
|
|
56
56
|
## Runtime context (`ctx`)
|
|
57
57
|
|
|
58
|
-
`ctx` is passed to your tool `execute`, hook handlers,
|
|
58
|
+
`ctx` is passed to your tool `execute`, hook handlers, channel event handlers, and connection auth/header resolvers. It is live only while authored code is running, so reaching for it at module top level throws. See [Session context](../guides/session-context) for the full model.
|
|
59
59
|
|
|
60
60
|
| Member | Use |
|
|
61
61
|
| --------------------------- | ---------------------------------------------------------------------------- |
|
package/docs/subagents.mdx
CHANGED
|
@@ -16,7 +16,7 @@ Every agent gets an `agent` tool by default. The model calls it to delegate a su
|
|
|
16
16
|
}
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
The copy shares the parent's sandbox and tools, and a child's file writes are immediately visible to the parent. That is what makes parallel calls natural: fan out a
|
|
19
|
+
The copy shares the parent's sandbox and tools, and a child's file writes are immediately visible to the parent. That is what makes parallel calls natural: emit multiple `agent` calls in one response to fan out a small, fixed set of independent subtasks. eve runs that batch concurrently and returns every result before the parent continues. Give children non-overlapping write scopes when they work in the shared sandbox. The copy inherits auth and connections, but starts with fresh conversation history and fresh state. If a declared subagent calls `agent`, the child is a copy of _that_ subagent, not the root.
|
|
20
20
|
|
|
21
21
|
The parent transfers data to the child through the `message` input it gives the subagent. Do not include sensitive data in a subagent request unless that child and its inherited tools, connections, sandbox, and telemetry path are appropriate for that data.
|
|
22
22
|
|
|
@@ -88,7 +88,7 @@ A declared subagent's tool name is the bare path-derived name, with no prefix. `
|
|
|
88
88
|
|
|
89
89
|
Because the name lives in the same runtime tool namespace as authored tools, a subagent named `researcher` collides with a tool named `researcher`. eve rejects the build rather than picking a winner, so keep subagent directory names distinct from tool names.
|
|
90
90
|
|
|
91
|
-
Do not rely on subagent delegation by itself as an approval boundary. Put sensitive tools behind `
|
|
91
|
+
Do not rely on subagent delegation by itself as an approval boundary. Put sensitive tools behind `approval`, connection approval, route/session authorization, or other controls wherever those tools can be called.
|
|
92
92
|
|
|
93
93
|
Each delegated subagent spins up its own child session and stream. The parent stream carries only the control-plane events `subagent.called` and `subagent.completed`. To follow the child's full progress, read `subagent.called.data.childSessionId` and subscribe at `GET /eve/v1/session/:childSessionId/stream`.
|
|
94
94
|
|
|
@@ -13,7 +13,7 @@ Either way the run parks at `session.waiting`, durably, for as long as it takes
|
|
|
13
13
|
|
|
14
14
|
## Approvals
|
|
15
15
|
|
|
16
|
-
Approval is a property of a [tool](/docs/tools) that pauses for a person before it runs. Gate a tool with `
|
|
16
|
+
Approval is a property of a [tool](/docs/tools) that pauses for a person before it runs. Gate a tool with `approval` and the helpers from `eve/tools/approval`:
|
|
17
17
|
|
|
18
18
|
```ts title="agent/tools/refund_charge.ts"
|
|
19
19
|
import { defineTool } from "eve/tools";
|
|
@@ -22,8 +22,8 @@ import { z } from "zod";
|
|
|
22
22
|
|
|
23
23
|
export default defineTool({
|
|
24
24
|
description: "Refund a charge.",
|
|
25
|
-
inputSchema: z.object({ chargeId: z.string(), amount: z.number() }),
|
|
26
|
-
|
|
25
|
+
inputSchema: z.object({ tenantId: z.string(), chargeId: z.string(), amount: z.number() }),
|
|
26
|
+
approval: always(), // or once() / never() / a policy
|
|
27
27
|
async execute(input) {
|
|
28
28
|
return refund(input);
|
|
29
29
|
},
|
|
@@ -36,16 +36,53 @@ export default defineTool({
|
|
|
36
36
|
| `once()` | Require approval only the first time the tool runs in a session; auto-allow after. |
|
|
37
37
|
| `always()` | Require approval before every call. |
|
|
38
38
|
|
|
39
|
-
By default, omitted `
|
|
39
|
+
By default, omitted `approval` behaves like `never()`, so tool calls may execute without human approval. Require human approval or other safeguards for sensitive, irreversible, regulated, financial, healthcare, employment, housing, legal, safety-impacting, user-impacting, or external side-effecting actions.
|
|
40
40
|
|
|
41
|
-
When the decision depends on the input, pass your own
|
|
41
|
+
When the decision depends on the input, pass your own policy instead of a helper. It receives the same session context as tool execution, plus `{ toolName, toolInput, approvedTools }`, and returns an AI SDK 7 approval status synchronously or as a promise. Use `ctx.session.auth.current` to guard by the caller of the current turn and `ctx.session.auth.initiator` to guard by the caller that created the session. Return `"user-approval"` to pause for a person or `"not-applicable"` to continue without a prompt. `toolInput` can be undefined, so guard the access. This policy denies cross-tenant calls, then requires approval only when an amount crosses a threshold:
|
|
42
42
|
|
|
43
43
|
```ts
|
|
44
|
-
|
|
44
|
+
approval: ({ session, toolInput }) => {
|
|
45
|
+
const callerTenant = session.auth.current?.attributes.tenantId;
|
|
46
|
+
if (callerTenant === undefined || callerTenant !== toolInput?.tenantId) {
|
|
47
|
+
return { type: "denied", reason: "Caller cannot access this tenant." };
|
|
48
|
+
}
|
|
49
|
+
return (toolInput?.amount ?? 0) > 1000 ? "user-approval" : "not-applicable";
|
|
50
|
+
},
|
|
45
51
|
```
|
|
46
52
|
|
|
53
|
+
For compatibility with the previous predicate shape, policies may return booleans: `true` is treated as `"user-approval"` and `false` as `"not-applicable"`. Boolean promises are supported too.
|
|
54
|
+
|
|
55
|
+
Policies can also return `"approved"` or `"denied"` to decide automatically. Use `{ type: "approved" | "denied", reason }` when the model should receive a reason. The `Approval`, `ApprovalContext`, and `ApprovalStatus` types are exported from both `eve/tools` and `eve/tools/approval`.
|
|
56
|
+
|
|
47
57
|
Gating a side effect on approval is also how you make non-idempotent work safe across replays: a charge or email that sits behind `always()` can't fire from a re-run step without a fresh human decision.
|
|
48
58
|
|
|
59
|
+
### Skipping approval for schedule-dispatched turns
|
|
60
|
+
|
|
61
|
+
`session.auth.current` identifies the caller of this turn. Markdown schedules use the app principal (`authenticator: "app"`, `principalId: "eve:app"`, `principalType: "runtime"`) automatically. A `run` schedule must pass its `appAuth` to `receive(...)` for the child session to use that principal. Match all three fields to skip approval for automated turns while still prompting when a person calls the same tool:
|
|
62
|
+
|
|
63
|
+
```ts title="agent/tools/refund_charge.ts"
|
|
64
|
+
import { defineTool } from "eve/tools";
|
|
65
|
+
import { z } from "zod";
|
|
66
|
+
|
|
67
|
+
export default defineTool({
|
|
68
|
+
description: "Refund a charge.",
|
|
69
|
+
inputSchema: z.object({ chargeId: z.string(), amount: z.number() }),
|
|
70
|
+
approval: ({ session }) => {
|
|
71
|
+
const auth = session.auth.current;
|
|
72
|
+
return auth?.authenticator === "app" &&
|
|
73
|
+
auth.principalId === "eve:app" &&
|
|
74
|
+
auth.principalType === "runtime"
|
|
75
|
+
? "not-applicable"
|
|
76
|
+
: "user-approval";
|
|
77
|
+
},
|
|
78
|
+
async execute(input) {
|
|
79
|
+
return refund(input);
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`session` in `approval` has the same shape as `ctx.session` in `execute`: `id`, `auth`, `turn`, and an optional `parent`. If a person later resumes a schedule-started session, `session.auth.current` becomes that person while `session.auth.initiator` remains the app principal. Inspect `initiator` only when the policy should apply to the whole session. Skipping approval on scheduled turns means any non-idempotent side effect will re-fire if a step replays, so pair this pattern with idempotency keys or `once()` where needed.
|
|
85
|
+
|
|
49
86
|
## Questions
|
|
50
87
|
|
|
51
88
|
The built-in `ask_question` tool lets the model pause and ask the user, rather than guessing. It has no `execute` — the model calls it with `{ prompt, options?, allowFreeform? }`:
|
package/docs/tools/overview.mdx
CHANGED
|
@@ -46,7 +46,7 @@ eve never runs authored tools during discovery. The model sees descriptors first
|
|
|
46
46
|
|
|
47
47
|
## Gate a tool on human approval
|
|
48
48
|
|
|
49
|
-
A tool can require a person to sign off before it runs. Set `
|
|
49
|
+
A tool can require a person to sign off before it runs. Set `approval` with the helpers from `eve/tools/approval`:
|
|
50
50
|
|
|
51
51
|
```ts title="agent/tools/refund_charge.ts"
|
|
52
52
|
import { defineTool } from "eve/tools";
|
|
@@ -56,14 +56,14 @@ import { z } from "zod";
|
|
|
56
56
|
export default defineTool({
|
|
57
57
|
description: "Refund a charge.",
|
|
58
58
|
inputSchema: z.object({ chargeId: z.string(), amount: z.number() }),
|
|
59
|
-
|
|
59
|
+
approval: always(), // or once() / never() / a policy
|
|
60
60
|
async execute(input) {
|
|
61
61
|
return refund(input);
|
|
62
62
|
},
|
|
63
63
|
});
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
-
Approval is one half of eve's [human-in-the-loop](./human-in-the-loop) model — the page covers the `always/once/never` helpers, input-dependent
|
|
66
|
+
Approval is one half of eve's [human-in-the-loop](./human-in-the-loop) model — the page covers the `always/once/never` helpers, input-dependent policies, and how a gated call pauses and resumes durably.
|
|
67
67
|
|
|
68
68
|
## Shape what the model sees with `toModelOutput`
|
|
69
69
|
|
|
@@ -10,7 +10,7 @@ Step 1 gets it talking. The scaffold bundles a small sample dataset, so your fir
|
|
|
10
10
|
## Prerequisites
|
|
11
11
|
|
|
12
12
|
- Node 24 or newer and npm.
|
|
13
|
-
- A model credential. The scaffold's default model goes through the [Vercel AI Gateway](../getting-started), so you need `AI_GATEWAY_API_KEY` (or `VERCEL_OIDC_TOKEN` pulled via `vercel link`). A direct provider model like `anthropic("claude-opus-4
|
|
13
|
+
- A model credential. The scaffold's default model goes through the [Vercel AI Gateway](../getting-started), so you need `AI_GATEWAY_API_KEY` (or `VERCEL_OIDC_TOKEN` pulled via `vercel link`). A direct provider model like `anthropic("claude-opus-4-8")` instead needs that provider's AI SDK package and key, here `@ai-sdk/anthropic` and `ANTHROPIC_API_KEY`.
|
|
14
14
|
|
|
15
15
|
If you have not run eve before, complete [Getting Started](../getting-started) first. Without a credential, "Run the agent" below fails when the runtime tries to reach the model; the dev TUI's `/model` flow walks you through pasting a key or linking a project.
|
|
16
16
|
|
|
@@ -5,7 +5,7 @@ description: "Part 8 of the Build an Agent tutorial. Gate expensive queries with
|
|
|
5
5
|
|
|
6
6
|
A single warehouse query can scan terabytes and run up the bill. So before the analytics assistant fires off an expensive scan, make it stop and check with you. The agent pauses, asks you, and resumes with your answer. That's human-in-the-loop, and you wire it up with one field on the tool.
|
|
7
7
|
|
|
8
|
-
`
|
|
8
|
+
`approval` runs before `execute`. Return `"user-approval"` and the turn parks on an approval request; you answer, and the run picks up from that exact step. The function gets the tool input, so you can make the decision cost-based.
|
|
9
9
|
|
|
10
10
|
## Estimate, then gate
|
|
11
11
|
|
|
@@ -32,7 +32,8 @@ export default defineTool({
|
|
|
32
32
|
description: "Run a read-only SQL query against the analytics tables.",
|
|
33
33
|
inputSchema: z.object({ sql: z.string() }),
|
|
34
34
|
// Cost-based gate: only the expensive queries need a human yes.
|
|
35
|
-
|
|
35
|
+
approval: ({ toolInput }) =>
|
|
36
|
+
estimateScanGb(toolInput?.sql ?? "") > THRESHOLD_GB ? "user-approval" : "not-applicable",
|
|
36
37
|
async execute({ sql }) {
|
|
37
38
|
const { columns, rows } = await runReadOnlySql(sql);
|
|
38
39
|
return { columns, rows: rows.slice(0, 500), truncated: rows.length > 500 };
|
|
@@ -50,7 +51,7 @@ Ask for something that forces a large unfiltered scan:
|
|
|
50
51
|
Total revenue across all customers, all time, broken out by day.
|
|
51
52
|
```
|
|
52
53
|
|
|
53
|
-
The model proposes the query, `
|
|
54
|
+
The model proposes the query, `approval` returns `"user-approval"`, and the turn parks. The stream emits `input.requested`, then `session.waiting`. How the prompt looks depends on the channel, whether buttons in the TUI, Block Kit in Slack, or a UI control on the web. Approve it and the run resumes from exactly that step, then the query runs. Deny it and the tool is skipped, with the model told why.
|
|
54
55
|
|
|
55
56
|
Each session has exactly one active continuation. Answer an approval against a stale handle and it's rejected, so there's no way to double-resume the same parked turn.
|
|
56
57
|
|
|
@@ -142,7 +142,7 @@ Across the nine steps you built and shipped one agent, and along the way you use
|
|
|
142
142
|
- **The sandbox** to compute and chart beyond SQL in an isolated `/workspace`.
|
|
143
143
|
- **State** (`defineState`) to remember the team's glossary across turns.
|
|
144
144
|
- **Dynamic skills** (`defineDynamic`) to load the right team playbook per caller.
|
|
145
|
-
- **Human-in-the-loop** approval (`
|
|
145
|
+
- **Human-in-the-loop** approval (`approval`) to gate expensive queries.
|
|
146
146
|
- **Channel auth** to turn a request into an authenticated principal.
|
|
147
147
|
- **Deployment** to Vercel, with the runtime behind your web app.
|
|
148
148
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eve",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
|
|
6
6
|
"keywords": [
|
|
@@ -267,12 +267,13 @@
|
|
|
267
267
|
"nitro": "3.0.260610-beta"
|
|
268
268
|
},
|
|
269
269
|
"devDependencies": {
|
|
270
|
-
"@ai-sdk/anthropic": "4.0.0
|
|
271
|
-
"@ai-sdk/google": "4.0.0
|
|
272
|
-
"@ai-sdk/mcp": "2.0.0
|
|
273
|
-
"@ai-sdk/openai": "4.0.0
|
|
274
|
-
"@ai-sdk/otel": "1.0.0
|
|
275
|
-
"@ai-sdk/provider": "4.0.0
|
|
270
|
+
"@ai-sdk/anthropic": "^4.0.0",
|
|
271
|
+
"@ai-sdk/google": "^4.0.0",
|
|
272
|
+
"@ai-sdk/mcp": "^2.0.0",
|
|
273
|
+
"@ai-sdk/openai": "^4.0.0",
|
|
274
|
+
"@ai-sdk/otel": "^1.0.0",
|
|
275
|
+
"@ai-sdk/provider": "^4.0.0",
|
|
276
|
+
"@ai-sdk/provider-utils": "^5.0.0",
|
|
276
277
|
"@chat-adapter/slack": "4.31.0",
|
|
277
278
|
"@chat-adapter/state-memory": "4.31.0",
|
|
278
279
|
"@clack/core": "1.3.1",
|
|
@@ -288,15 +289,17 @@
|
|
|
288
289
|
"@vercel/sdk": "1.28.1",
|
|
289
290
|
"@workflow/core": "5.0.0-beta.24",
|
|
290
291
|
"@workflow/errors": "5.0.0-beta.8",
|
|
292
|
+
"@workflow/serde": "4.1.0",
|
|
291
293
|
"@workflow/world": "5.0.0-beta.13",
|
|
292
294
|
"@workflow/world-local": "5.0.0-beta.21",
|
|
293
|
-
"ai": "7.0.0
|
|
295
|
+
"ai": "^7.0.0",
|
|
294
296
|
"autoevals": "0.0.132",
|
|
295
297
|
"chat": "4.31.0",
|
|
296
298
|
"chokidar": "5.0.0",
|
|
297
299
|
"commander": "14.0.3",
|
|
298
|
-
"emulate": "
|
|
299
|
-
"
|
|
300
|
+
"emulate": "0.6.0",
|
|
301
|
+
"eventsource-parser": "3.0.8",
|
|
302
|
+
"experimental-ai-sdk-code-mode": "1.0.16",
|
|
300
303
|
"gray-matter": "4.0.3",
|
|
301
304
|
"jose": "6.2.3",
|
|
302
305
|
"jsonc-parser": "3.3.1",
|
|
@@ -319,7 +322,7 @@
|
|
|
319
322
|
"peerDependencies": {
|
|
320
323
|
"@opentelemetry/api": "^1.0.0",
|
|
321
324
|
"@sveltejs/kit": "^2.0.0",
|
|
322
|
-
"ai": "7.0.0
|
|
325
|
+
"ai": "^7.0.0",
|
|
323
326
|
"braintrust": "^3.0.0",
|
|
324
327
|
"just-bash": "^3.0.0",
|
|
325
328
|
"microsandbox": "^0.5.0",
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// Auto-generated stub for `@ai-sdk/provider-utils` types referenced by a vendored .d.ts.
|
|
2
|
-
// Emitted by createDeclarationCopier > buildOpaqueTypesStub.
|
|
3
|
-
//
|
|
4
|
-
// Names are aliased to `unknown` so consumers don't have to install
|
|
5
|
-
// upstream @types just to typecheck against eve. If real types are
|
|
6
|
-
// needed in user code, install the upstream @types and use them directly.
|
|
7
|
-
|
|
8
|
-
export type Experimental_SandboxSession = unknown;
|
|
9
|
-
export type FetchFunction = unknown;
|
|
10
|
-
export type ProviderDefinedTool = unknown;
|
|
11
|
-
export type ProviderDefinedToolFactory = unknown;
|
|
12
|
-
export type ProviderExecutedTool = unknown;
|
|
13
|
-
export type ProviderExecutedToolFactory = unknown;
|
|
14
|
-
export type Tool = unknown;
|
|
15
|
-
export type ToolExecuteFunction = unknown;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
// Auto-generated stub for `@ai-sdk/provider-utils` types referenced by a vendored .d.ts.
|
|
2
|
-
// Emitted by createDeclarationCopier > buildOpaqueTypesStub.
|
|
3
|
-
//
|
|
4
|
-
// Names are aliased to `unknown` so consumers don't have to install
|
|
5
|
-
// upstream @types just to typecheck against eve. If real types are
|
|
6
|
-
// needed in user code, install the upstream @types and use them directly.
|
|
7
|
-
|
|
8
|
-
export type FetchFunction = unknown;
|
|
9
|
-
export type InferSchema = unknown;
|
|
10
|
-
export type LazySchema = unknown;
|
|
11
|
-
export type ProviderExecutedToolFactory = unknown;
|