eve 0.20.0 → 0.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/dist/src/channel/types.d.ts +9 -5
- package/dist/src/chunks/{use-eve-agent-Dvy_Wjvq.js → use-eve-agent-CM24ZUEI.js} +48 -34
- package/dist/src/chunks/{use-eve-agent-Bh1NmXO9.js → use-eve-agent-CxcKypLZ.js} +48 -34
- package/dist/src/client/index.d.ts +1 -1
- package/dist/src/client/message-reducer-types.d.ts +11 -3
- package/dist/src/client/message-reducer.js +1 -1
- package/dist/src/compiler/manifest.js +1 -1
- package/dist/src/compiler/normalize-agent-config.js +1 -1
- package/dist/src/compiler/workspace-resources.js +1 -1
- package/dist/src/context/dynamic-skill-lifecycle.js +1 -1
- package/dist/src/context/keys.d.ts +0 -1
- package/dist/src/context/keys.js +1 -1
- package/dist/src/discover/sandbox.d.ts +0 -6
- package/dist/src/discover/sandbox.js +1 -1
- package/dist/src/evals/cli/eval.js +2 -2
- package/dist/src/execution/create-session-step.d.ts +2 -1
- package/dist/src/execution/create-session-step.js +1 -1
- package/dist/src/execution/delegated-parent-notification.d.ts +6 -0
- package/dist/src/execution/delegated-parent-notification.js +1 -1
- package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
- package/dist/src/execution/dispatch-workflow-runtime-actions-step.js +1 -1
- package/dist/src/execution/durable-session-store.d.ts +1 -0
- package/dist/src/execution/next-driver-action.d.ts +3 -0
- package/dist/src/execution/node-step.d.ts +6 -0
- package/dist/src/execution/node-step.js +1 -1
- package/dist/src/execution/run-session-limits.d.ts +21 -0
- package/dist/src/execution/run-session-limits.js +1 -0
- package/dist/src/execution/runtime-context.js +1 -1
- package/dist/src/execution/sandbox/bindings/local-backend-utils.d.ts +1 -1
- package/dist/src/execution/sandbox/bindings/local-backend-utils.js +1 -1
- package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
- package/dist/src/execution/sandbox/ensure.js +1 -1
- package/dist/src/execution/sandbox/prewarm.js +1 -1
- package/dist/src/execution/session-callback-step.d.ts +6 -0
- package/dist/src/execution/session-callback-step.js +1 -1
- package/dist/src/execution/session.d.ts +14 -3
- package/dist/src/execution/session.js +2 -4
- package/dist/src/execution/skills/instructions.d.ts +8 -4
- package/dist/src/execution/skills/instructions.js +2 -2
- package/dist/src/execution/subagent-tool.d.ts +7 -0
- package/dist/src/execution/subagent-tool.js +1 -1
- package/dist/src/execution/subagent-usage-span.d.ts +9 -0
- package/dist/src/execution/subagent-usage-span.js +1 -0
- package/dist/src/execution/turn-execution-cursor.d.ts +2 -0
- package/dist/src/execution/turn-workflow.js +1 -1
- package/dist/src/execution/workflow-entry.d.ts +1 -0
- package/dist/src/execution/workflow-entry.js +1 -1
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/execution/workflow-skill-root.d.ts +6 -0
- package/dist/src/execution/workflow-skill-root.js +1 -0
- package/dist/src/execution/workflow-steps.d.ts +3 -0
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/harness/advertised-tools.d.ts +1 -0
- package/dist/src/harness/advertised-tools.js +1 -1
- package/dist/src/harness/input-requests.d.ts +8 -0
- package/dist/src/harness/input-requests.js +1 -1
- package/dist/src/harness/runtime-actions.js +1 -1
- package/dist/src/harness/session-limit-continuation.d.ts +55 -0
- package/dist/src/harness/session-limit-continuation.js +1 -0
- package/dist/src/harness/session-limit-enforcement.d.ts +55 -0
- package/dist/src/harness/session-limit-enforcement.js +1 -0
- package/dist/src/harness/subagent-depth.d.ts +1 -4
- package/dist/src/harness/subagent-depth.js +1 -1
- package/dist/src/harness/subagent-token-budget.d.ts +14 -0
- package/dist/src/harness/subagent-token-budget.js +1 -0
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/harness/turn-tag-state.d.ts +31 -0
- package/dist/src/harness/turn-tag-state.js +1 -1
- package/dist/src/harness/types.d.ts +21 -4
- package/dist/src/harness/workflow-sandbox.d.ts +1 -0
- package/dist/src/harness/workflow-sandbox.js +1 -1
- package/dist/src/harness/workflow-subagent-limit.d.ts +38 -0
- package/dist/src/harness/workflow-subagent-limit.js +1 -0
- package/dist/src/harness/workflow-tool-description.d.ts +6 -1
- package/dist/src/harness/workflow-tool-description.js +5 -3
- package/dist/src/internal/application/package.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/sandbox-shutdown-plugin.js +1 -1
- package/dist/src/protocol/message.d.ts +19 -2
- package/dist/src/protocol/message.js +2 -2
- package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +34 -3
- package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
- package/dist/src/public/channels/chat-sdk/index.d.ts +2 -0
- package/dist/src/public/channels/chat-sdk/index.js +1 -1
- package/dist/src/public/channels/chat-sdk/messageToUserContent.d.ts +13 -0
- package/dist/src/public/channels/chat-sdk/messageToUserContent.js +1 -0
- package/dist/src/public/channels/chat-sdk/notImplemented.d.ts +7 -0
- package/dist/src/public/channels/chat-sdk/notImplemented.js +1 -0
- package/dist/src/public/channels/slack/api.d.ts +14 -12
- package/dist/src/public/channels/slack/api.js +1 -1
- package/dist/src/public/definitions/tool.d.ts +37 -0
- package/dist/src/public/definitions/tool.js +1 -1
- package/dist/src/public/tools/index.d.ts +1 -1
- package/dist/src/public/tools/index.js +1 -1
- package/dist/src/runtime/actions/types.d.ts +9 -0
- package/dist/src/runtime/actions/types.js +1 -1
- package/dist/src/runtime/agent/bootstrap.d.ts +2 -0
- package/dist/src/runtime/agent/bootstrap.js +1 -1
- package/dist/src/runtime/resolve-agent.js +1 -1
- package/dist/src/runtime/sandbox/keys.js +1 -1
- package/dist/src/runtime/sandbox/template-plan.js +1 -1
- package/dist/src/runtime/session-callback-route.js +1 -1
- package/dist/src/runtime/skills/sandbox-access.d.ts +1 -1
- package/dist/src/runtime/skills/sandbox-access.js +1 -1
- package/dist/src/runtime/workspace/seed-files.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/setup/scaffold/create/web-template.d.ts +2 -2
- package/dist/src/setup/scaffold/create/web-template.js +77 -3
- package/dist/src/shared/agent-definition.d.ts +31 -3
- package/dist/src/shared/skill-package.d.ts +2 -2
- package/dist/src/shared/skill-package.js +1 -1
- package/dist/src/shared/skill-paths.d.ts +28 -0
- package/dist/src/shared/skill-paths.js +2 -0
- package/dist/src/shared/token-usage.d.ts +22 -0
- package/dist/src/shared/token-usage.js +1 -0
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/agent-config.md +32 -15
- package/docs/channels/chat-sdk.mdx +209 -0
- package/docs/channels/meta.json +1 -0
- package/docs/concepts/context-control.md +2 -2
- package/docs/concepts/default-harness.md +10 -0
- package/docs/concepts/sessions-runs-and-streaming.md +1 -1
- package/docs/guides/client/messages.mdx +4 -0
- package/docs/guides/client/streaming.mdx +17 -12
- package/docs/guides/dynamic-workflows.md +87 -0
- package/docs/guides/frontend/overview.mdx +5 -1
- package/docs/guides/meta.json +1 -0
- package/docs/guides/remote-agents.md +1 -0
- package/docs/reference/project-layout.md +5 -4
- package/docs/reference/typescript-api.md +26 -26
- package/docs/sandbox.mdx +1 -1
- package/docs/skills.mdx +3 -1
- package/docs/subagents.mdx +2 -1
- package/package.json +1 -1
package/docs/agent-config.md
CHANGED
|
@@ -93,13 +93,30 @@ export default defineAgent({
|
|
|
93
93
|
|
|
94
94
|
Input and output budgets are checked independently. The model call that crosses
|
|
95
95
|
either limit is allowed to finish because providers only report exact token
|
|
96
|
-
usage after a call completes.
|
|
97
|
-
with
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
`
|
|
101
|
-
|
|
102
|
-
|
|
96
|
+
usage after a call completes. Before the next model call, eve pauses the
|
|
97
|
+
session and sends a deterministic continuation prompt with two options:
|
|
98
|
+
**Continue** grants a fresh budget window of the configured size (both input
|
|
99
|
+
and output windows reset together), and **Stop** ends the session gracefully
|
|
100
|
+
(`session.completed`) — declining is a user decision, not an error. A reply
|
|
101
|
+
that answers neither option re-raises the prompt; the reply stays in history
|
|
102
|
+
and is processed once the budget is granted.
|
|
103
|
+
|
|
104
|
+
Sessions that cannot reach a human — task-mode runs such as schedules and
|
|
105
|
+
subagents without input proxying — skip the prompt and fail the next model
|
|
106
|
+
call with `SESSION_TOKEN_LIMIT_REACHED`.
|
|
107
|
+
|
|
108
|
+
When `maxInputTokensPerSession` is omitted, root sessions apply a default
|
|
109
|
+
input budget of `40_000_000` provider-reported input tokens.
|
|
110
|
+
`maxOutputTokensPerSession` is unset unless configured. Setting either limit
|
|
111
|
+
to `false` uncaps that axis — the session never stops on it.
|
|
112
|
+
|
|
113
|
+
Delegated subagent sessions have no fixed default. Each child receives a
|
|
114
|
+
share of the delegating parent's remaining quota at dispatch time — the
|
|
115
|
+
remainder (limit minus accumulated usage) split evenly across the batch's
|
|
116
|
+
local subagent calls — and a completed child's usage counts against the
|
|
117
|
+
parent's quota, so a delegation tree can never outspend the budget configured
|
|
118
|
+
at its root. An authored child limit applies only when it is tighter than the
|
|
119
|
+
parent's grant; an uncapped parent delegates uncapped children.
|
|
103
120
|
|
|
104
121
|
## Workflow world
|
|
105
122
|
|
|
@@ -142,14 +159,14 @@ installed package must stay external in hosted output, list it in
|
|
|
142
159
|
|
|
143
160
|
`defineAgent` takes a few more fields, all optional. For the exported types, see the [TypeScript API](./reference/typescript-api).
|
|
144
161
|
|
|
145
|
-
| Field | Type | Default | Description
|
|
146
|
-
| -------------- | --------------------------------------- | ---------------- |
|
|
147
|
-
| `reasoning` | `AgentReasoningDefinition` | provider default | Provider-agnostic reasoning effort forwarded to the agent's turn model calls.
|
|
148
|
-
| `modelOptions` | `AgentModelOptionsDefinition` | none | Provider option overrides forwarded to the model call.
|
|
149
|
-
| `limits` | `AgentLimitsDefinition` | field-specific | Framework-owned runtime limits. `maxSubagentDepth` defaults to `3`; `maxInputTokensPerSession` defaults to `40_000_000` for root sessions and
|
|
150
|
-
| `experimental` | `{ workflow?: { world?: string } }` | unset | Opt-in settings that can change or disappear in any release. Treat them as unstable. `workflow.world` selects the Workflow world package backing session state, queues, hooks, and streams on the root agent.
|
|
151
|
-
| `outputSchema` | Standard Schema or a JSON Schema object | none | Structured return type for task-mode runs (a subagent, schedule, or remote job). Interactive conversation turns ignore it unless the client supplies a per-message schema.
|
|
152
|
-
| `build` | `{ externalDependencies?: string[] }` | none | Hosted-build packaging controls. `externalDependencies` keeps listed packages external while eve compiles authored modules such as tools and channels, and traces those packages into the hosted output.
|
|
162
|
+
| Field | Type | Default | Description |
|
|
163
|
+
| -------------- | --------------------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
164
|
+
| `reasoning` | `AgentReasoningDefinition` | provider default | Provider-agnostic reasoning effort forwarded to the agent's turn model calls. |
|
|
165
|
+
| `modelOptions` | `AgentModelOptionsDefinition` | none | Provider option overrides forwarded to the model call. |
|
|
166
|
+
| `limits` | `AgentLimitsDefinition` | field-specific | Framework-owned runtime limits. `maxSubagentDepth` defaults to `3`; `maxInputTokensPerSession` defaults to `40_000_000` for root sessions, and delegated subagent sessions inherit the parent's remaining quota; `maxOutputTokensPerSession` is unset unless configured; `false` uncaps a session token limit. |
|
|
167
|
+
| `experimental` | `{ workflow?: { world?: string } }` | unset | Opt-in settings that can change or disappear in any release. Treat them as unstable. `workflow.world` selects the Workflow world package backing session state, queues, hooks, and streams on the root agent. |
|
|
168
|
+
| `outputSchema` | Standard Schema or a JSON Schema object | none | Structured return type for task-mode runs (a subagent, schedule, or remote job). Interactive conversation turns ignore it unless the client supplies a per-message schema. |
|
|
169
|
+
| `build` | `{ externalDependencies?: string[] }` | none | Hosted-build packaging controls. `externalDependencies` keeps listed packages external while eve compiles authored modules such as tools and channels, and traces those packages into the hosted output. |
|
|
153
170
|
|
|
154
171
|
`externalDependencies` is a packaging control only. It keeps selected packages as runtime dependencies in the hosted output; it does not authorize, configure, or review any third-party service those packages may call.
|
|
155
172
|
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Chat SDK"
|
|
3
|
+
description: "Bridge any Vercel Chat SDK adapter — Slack, Discord, Telegram, WhatsApp, email, and more — to your agent through one channel, using your own credentials and state store."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
The Chat SDK channel connects your agent to any [Vercel Chat SDK](https://chat-sdk.dev) adapter. You pick an adapter (`@chat-adapter/slack`, `@resend/chat-sdk-adapter`, and so on), register handlers for the messages you care about, and call `send` to hand each turn to eve. Use it to reach a surface eve does not ship a first-class channel for, or when you want to manage credentials and state with the Chat SDK's own primitives rather than [Vercel Connect](../guides/auth-and-route-protection). See [Channels](./overview) for the contract this builds on.
|
|
7
|
+
|
|
8
|
+
You supply an adapter and a state store: the adapter owns provider auth, webhook verification, and delivery, while eve owns session dispatch, streaming, typing, and human-in-the-loop. First-class channels such as [Slack](./slack) manage credentials through Vercel Connect instead — reach for whichever fits the surface you are targeting.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
Add eve, the Chat SDK core (`chat`), an adapter, and a state adapter. The example below uses the Resend email adapter with the in-memory state store:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install eve@latest chat @resend/chat-sdk-adapter @chat-adapter/state-memory
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Swap in whichever adapter matches your surface — `@chat-adapter/slack`, `@chat-adapter/discord`, `@chat-adapter/telegram`, and so on. Any Chat SDK adapter works.
|
|
19
|
+
|
|
20
|
+
## Add the channel
|
|
21
|
+
|
|
22
|
+
`chatSdkChannel` returns `{ bot, channel, send }`. Register Chat SDK handlers on `bot`, call `send` from those handlers to start or resume an eve session, and export `channel` as the module default:
|
|
23
|
+
|
|
24
|
+
```ts title="agent/channels/resend.ts"
|
|
25
|
+
import { createMemoryState } from "@chat-adapter/state-memory";
|
|
26
|
+
import { createResendAdapter } from "@resend/chat-sdk-adapter";
|
|
27
|
+
import type { Message, Thread } from "chat";
|
|
28
|
+
import { chatSdkChannel } from "eve/channels/chat-sdk";
|
|
29
|
+
|
|
30
|
+
export const { bot, channel, send } = chatSdkChannel({
|
|
31
|
+
userName: "Resend Bot",
|
|
32
|
+
adapters: {
|
|
33
|
+
resend: createResendAdapter({
|
|
34
|
+
fromAddress: "hello@example.com",
|
|
35
|
+
fromName: "Resend Bot",
|
|
36
|
+
}),
|
|
37
|
+
},
|
|
38
|
+
state: createMemoryState(),
|
|
39
|
+
streaming: false,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
bot.onNewMention(async (thread: Thread, message: Message) => {
|
|
43
|
+
await thread.subscribe();
|
|
44
|
+
await send(message.text, { thread });
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
bot.onSubscribedMessage(async (thread: Thread, message: Message) => {
|
|
48
|
+
await send(message.text, { thread });
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
export default channel;
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`adapters` is a map of adapter name to adapter instance; each entry mounts its own webhook (see below). `state` takes any Chat SDK state adapter: `createMemoryState()` is fine for local development, but use a durable adapter (Redis, Upstash, etc.) in production so thread subscriptions and inbound deduplication survive restarts. `send` accepts a plain string, an AI SDK `UserContent` array, or a `SendPayload`, and must be called from inside a Chat SDK handler — it dispatches the turn on the webhook that is currently running.
|
|
55
|
+
|
|
56
|
+
Deploy once the channel file is in place:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
eve deploy
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`eve deploy` links the project if needed and deploys to Vercel production.
|
|
63
|
+
|
|
64
|
+
## Configure the webhook route
|
|
65
|
+
|
|
66
|
+
Each adapter mounts one `POST` route at `/eve/v1/{adapterName}`, so the `resend` adapter above is served at `/eve/v1/resend`. Point your provider's webhook (the Resend inbound address, the Slack Event Subscriptions URL, etc.) at that path.
|
|
67
|
+
|
|
68
|
+
Override the base path for every adapter with `route`, or pin an individual adapter's path with `routes`:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
export const { bot, channel, send } = chatSdkChannel({
|
|
72
|
+
userName: "Resend Bot",
|
|
73
|
+
adapters: { resend: createResendAdapter({ fromAddress: "hello@example.com" }) },
|
|
74
|
+
state: createMemoryState(),
|
|
75
|
+
route: "/webhooks", // resend now mounts at /webhooks/resend
|
|
76
|
+
routes: { resend: "/webhooks/inbound-email" }, // …or pin it exactly
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Use `routes` when a provider requires a fixed URL or when you are migrating an existing endpoint without changing the provider's settings.
|
|
81
|
+
|
|
82
|
+
## How the channel handles messages
|
|
83
|
+
|
|
84
|
+
### Dispatch
|
|
85
|
+
|
|
86
|
+
You choose which Chat SDK events start a turn by registering handlers on `bot` and calling `send`:
|
|
87
|
+
|
|
88
|
+
- `bot.onNewMention(thread, message)` fires on a fresh `@mention` (or, for surfaces like email, a new inbound thread). Call `thread.subscribe()` when you want later replies in the same thread to keep reaching the agent.
|
|
89
|
+
- `bot.onSubscribedMessage(thread, message)` fires on subsequent messages in a subscribed thread.
|
|
90
|
+
- `bot.onAction`, `bot.onReaction`, and `bot.onSlashCommand` are available for adapters that emit them.
|
|
91
|
+
|
|
92
|
+
`send(input, options)` starts or resumes the eve session. The `thread` you pass determines the continuation token and the persisted channel state, so replies land back on the originating thread:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
bot.onNewMention(async (thread, message) => {
|
|
96
|
+
await send(message.text, { thread, title: "Support request" });
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`options` accepts `{ thread, auth?, title?, mode?, callback?, adapterName? }`. `title` sets the eve session's display title without changing the model message; `auth` attaches an authenticated principal to the turn.
|
|
101
|
+
|
|
102
|
+
### Delivery
|
|
103
|
+
|
|
104
|
+
The default handlers post the agent's reply back to the thread — no `events` override required. Completed assistant messages are posted as markdown (`{ markdown: … }`) so adapters render rich text and email HTML rather than a raw string.
|
|
105
|
+
|
|
106
|
+
Streaming is on by default: the channel posts an initial message and edits it as tokens arrive (`message.appended`), throttled by `streamingEditIntervalMs` (default `1000`). Set `streaming: false` for surfaces that deliver one message per turn — email, for example — so the reply posts once on completion instead of editing:
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
chatSdkChannel({
|
|
110
|
+
userName: "Resend Bot",
|
|
111
|
+
adapters: { resend: createResendAdapter({ fromAddress: "hello@example.com" }) },
|
|
112
|
+
state: createMemoryState(),
|
|
113
|
+
streaming: false,
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Typing indicators post automatically where the adapter supports them: `Working…` on `turn.started`, and tool status on `actions.requested`.
|
|
118
|
+
|
|
119
|
+
### Optional capabilities degrade gracefully
|
|
120
|
+
|
|
121
|
+
Adapters do not all implement every operation. When an adapter's `startTyping` or `editMessage` throws a `NotImplementedError` (or an error with code `NOT_IMPLEMENTED`), the channel swallows it: typing indicators are skipped, and a streaming edit falls back to a single final post for the rest of the session. You never have to guard optional capabilities in your own handlers. The same predicate is exported as `isNotImplemented` if you want it in custom `events`:
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
import { isNotImplemented } from "eve/channels/chat-sdk";
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Override any default by passing `events`. Handlers receive `(eventData, channel, ctx)`, with the rebuilt Chat SDK thread on `channel.thread`:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
chatSdkChannel({
|
|
131
|
+
userName: "Resend Bot",
|
|
132
|
+
adapters: { resend: createResendAdapter({ fromAddress: "hello@example.com" }) },
|
|
133
|
+
state: createMemoryState(),
|
|
134
|
+
events: {
|
|
135
|
+
"message.completed"(eventData, channel) {
|
|
136
|
+
if (eventData.finishReason === "tool-calls" || !eventData.message || !channel.thread) return;
|
|
137
|
+
return channel.thread.post({ markdown: eventData.message });
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Human-in-the-loop (HITL)
|
|
144
|
+
|
|
145
|
+
HITL prompts render as a Chat SDK `Card` with buttons. Button clicks resume the parked session automatically — the channel wires `bot.onAction` for you. Change the action-id prefix with `inputActionPrefix` (default `eve_input:`) if your app already uses it, and provide `resolveInputAuth` to carry user or tenant auth across the resume:
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
chatSdkChannel({
|
|
149
|
+
userName: "Support Bot",
|
|
150
|
+
adapters: { slack: createSlackAdapter() },
|
|
151
|
+
state: createMemoryState(),
|
|
152
|
+
resolveInputAuth: (event) => ({
|
|
153
|
+
authenticator: "slack",
|
|
154
|
+
principalType: "user",
|
|
155
|
+
principalId: event.user?.userId ?? "unknown",
|
|
156
|
+
attributes: {},
|
|
157
|
+
}),
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Proactive sessions
|
|
162
|
+
|
|
163
|
+
Start a session without an inbound webhook through `channel.receive({ message, target, auth })` — from a schedule `run` handler, or `args.receive(channel, ...)` from another channel. The target is a serialized Chat SDK thread, or `{ threadId, adapterName }` when you only have a provider-native thread id:
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
await channel.receive({
|
|
167
|
+
message: "Your weekly digest is ready.",
|
|
168
|
+
target: { adapterName: "resend", threadId: "resend:user@example.com" },
|
|
169
|
+
auth: null,
|
|
170
|
+
});
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Attachments
|
|
174
|
+
|
|
175
|
+
`send` takes plain text or an AI SDK `UserContent` array. To forward a Chat SDK message's attachments, convert it with `messageToUserContent`, which returns `message.text` when there are no attachments and a `UserContent` array (text plus one file part per attachment URL) when there are:
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
import { messageToUserContent } from "eve/channels/chat-sdk";
|
|
179
|
+
|
|
180
|
+
bot.onNewMention(async (thread, message) => {
|
|
181
|
+
await send(messageToUserContent(message), { thread });
|
|
182
|
+
});
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
See [File uploads](./custom#file-uploads) for how eve stages remote file URLs before the model call.
|
|
186
|
+
|
|
187
|
+
## Configuration reference
|
|
188
|
+
|
|
189
|
+
| Option | Default | Purpose |
|
|
190
|
+
| ------------------------- | ------------ | ------------------------------------------------------------------------ |
|
|
191
|
+
| `adapters` | — | Map of adapter name to Chat SDK adapter instance. One webhook per entry. |
|
|
192
|
+
| `state` | — | Chat SDK state adapter for subscriptions, locks, and dedupe. |
|
|
193
|
+
| `userName` | — | Display name for the bot (a standard Chat SDK `ChatConfig` field). |
|
|
194
|
+
| `route` | `/eve/v1` | Base path for generated adapter webhooks (`{route}/{adapter}`). |
|
|
195
|
+
| `routes` | — | Per-adapter path overrides for fixed or migrated webhook URLs. |
|
|
196
|
+
| `streaming` | `true` | Post-then-edit streaming. Set `false` for one-message-per-turn surfaces. |
|
|
197
|
+
| `streamingEditIntervalMs` | `1000` | Minimum interval between streaming edits. |
|
|
198
|
+
| `events` | built-in | Per-event handlers. A supplied handler replaces that built-in default. |
|
|
199
|
+
| `inputActionPrefix` | `eve_input:` | Prefix for default HITL button action ids. |
|
|
200
|
+
| `resolveInputAuth` | `null` | Auth resolver applied when a HITL button click resumes a session. |
|
|
201
|
+
| `webhook` | — | Extra Chat SDK webhook options (eve owns `waitUntil`). |
|
|
202
|
+
|
|
203
|
+
Any other Chat SDK `ChatConfig` field (for example `concurrency`) is accepted and passed through.
|
|
204
|
+
|
|
205
|
+
## What to read next
|
|
206
|
+
|
|
207
|
+
- [Channels overview](./overview): the channel contract and every built-in channel
|
|
208
|
+
- [Custom channels](./custom): build a channel for any surface with `defineChannel`
|
|
209
|
+
- [Auth & route protection](../guides/auth-and-route-protection): authenticating inbound traffic
|
package/docs/channels/meta.json
CHANGED
|
@@ -52,13 +52,13 @@ When the task is novel or ambiguous, gather evidence first, then answer with the
|
|
|
52
52
|
remaining uncertainty.
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
Packaged skills are useful when you also want sibling files such as `references/`, `assets/`, or `scripts/` under the same skill directory. Those
|
|
55
|
+
Packaged skills are useful when you also want sibling files such as `references/`, `assets/`, or `scripts/` under the same skill directory. Those files are available under the runtime skill root, normally `$HOME/.agents/skills/<skill>/`. Relative references inside a `SKILL.md` resolve from that specific skill directory, so `references/checklist.md` means `$HOME/.agents/skills/<skill>/references/checklist.md` unless eve has fallen back to `/workspace/skills/<skill>/`.
|
|
56
56
|
|
|
57
57
|
See [Skills](../skills) for the full authoring model and install notes.
|
|
58
58
|
|
|
59
59
|
## Put runtime files in the workspace, not the prompt
|
|
60
60
|
|
|
61
|
-
eve does not inline the entire authored surface into the prompt. Instead, it gives the model a shallow workspace hint and runtime tools to inspect deeper when needed. Skill files are
|
|
61
|
+
eve does not inline the entire authored surface into the prompt. Instead, it gives the model a shallow workspace hint, a separate skill-root hint, and runtime tools to inspect deeper when needed. Skill package files are outside `/workspace` in the normal case, and the model inspects them with the shared `bash` tool, which keeps prompts smaller and makes file and command work explicit.
|
|
62
62
|
|
|
63
63
|
See [Sandbox](../sandbox) for the workspace and sandbox model.
|
|
64
64
|
|
|
@@ -87,6 +87,16 @@ Three moves shape the harness. The right one depends on whether the model should
|
|
|
87
87
|
- **Disable** when the model should not have the capability at all. A `disableTool()` sentinel removes the built-in, and the model never sees it. Reach for this to lock down `bash` or `web_fetch` in an agent that should not run shell commands or fetch arbitrary URLs.
|
|
88
88
|
- **Author a new tool** when you want a capability the harness does not ship. Give it a fresh slug under `agent/tools/` and it joins the built-ins instead of replacing one. See [Tools](../tools) for the authoring model.
|
|
89
89
|
|
|
90
|
+
## The opt-in `Workflow` tool
|
|
91
|
+
|
|
92
|
+
An experimental `Workflow` tool ships but stays off by default. To turn it on, re-export the opt-in marker from `agent/tools/workflow.ts`:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
export { ExperimentalWorkflow as default } from "eve/tools";
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
With it on, the model can orchestrate the agent's own subagents from model-authored JavaScript, all as one durable step. The tool is root-only — delegated subagent sessions never see it — and one program may dispatch at most `limits.maxSubagents` subagent calls (default 100). See [Dynamic workflows](../guides/dynamic-workflows).
|
|
99
|
+
|
|
90
100
|
## What to read next
|
|
91
101
|
|
|
92
102
|
- [Tools](../tools): define your own tools, gate them on approval, and shape their output with `toModelOutput`
|
|
@@ -38,7 +38,7 @@ The stream is newline-delimited JSON (NDJSON), one event per line:
|
|
|
38
38
|
| ------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
39
39
|
| `session.started` | A durable session was created. |
|
|
40
40
|
| `turn.started` | A new turn began. |
|
|
41
|
-
| `message.received` | An inbound user message was accepted.
|
|
41
|
+
| `message.received` | An inbound user message was accepted; carries flattened text plus structured text/file parts. |
|
|
42
42
|
| `step.started` | A model step began. |
|
|
43
43
|
| `actions.requested` | The model requested one or more actions, including tool calls; calls stream before execution. |
|
|
44
44
|
| `action.result` | A tool call returned. |
|
|
@@ -98,6 +98,10 @@ const response = await session.send({
|
|
|
98
98
|
await response.result();
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
+
The stream confirms the turn with `message.received`. Its `data.message` remains the flattened
|
|
102
|
+
summary for compatibility, and `data.parts` contains structured text and file metadata for clients
|
|
103
|
+
that render attachments. File parts never include raw bytes or internal sandbox paths.
|
|
104
|
+
|
|
101
105
|
## Answer human input requests
|
|
102
106
|
|
|
103
107
|
Tools can pause for approval or ask the user a question. The stream emits `input.requested` with one or more requests. Reply through the same session with `inputResponses`:
|
|
@@ -61,21 +61,26 @@ function handleEvent(event: HandleMessageStreamEvent) {
|
|
|
61
61
|
|
|
62
62
|
The most common UI events are:
|
|
63
63
|
|
|
64
|
-
| Event | Use
|
|
65
|
-
| -------------------- |
|
|
66
|
-
| `message.received` | Confirm the user message landed.
|
|
67
|
-
| `reasoning.appended` | Render reasoning deltas when the model provides them.
|
|
68
|
-
| `message.appended` | Render assistant text deltas.
|
|
69
|
-
| `actions.requested` | Show tool calls as the model requests them, before execution.
|
|
70
|
-
| `action.result` | Show tool call results.
|
|
71
|
-
| `input.requested` | Pause the UI for approval or a question answer.
|
|
72
|
-
| `result.completed` | Read structured output from an [output schema](./output-schema).
|
|
73
|
-
| `session.waiting` | Enable the composer for the next turn.
|
|
74
|
-
| `session.completed` | Mark the conversation terminal.
|
|
75
|
-
| `session.failed` | Mark the conversation failed.
|
|
64
|
+
| Event | Use |
|
|
65
|
+
| -------------------- | ------------------------------------------------------------------------------ |
|
|
66
|
+
| `message.received` | Confirm the user message landed; `data.parts` includes text and file metadata. |
|
|
67
|
+
| `reasoning.appended` | Render reasoning deltas when the model provides them. |
|
|
68
|
+
| `message.appended` | Render assistant text deltas. |
|
|
69
|
+
| `actions.requested` | Show tool calls as the model requests them, before execution. |
|
|
70
|
+
| `action.result` | Show tool call results. |
|
|
71
|
+
| `input.requested` | Pause the UI for approval or a question answer. |
|
|
72
|
+
| `result.completed` | Read structured output from an [output schema](./output-schema). |
|
|
73
|
+
| `session.waiting` | Enable the composer for the next turn. |
|
|
74
|
+
| `session.completed` | Mark the conversation terminal. |
|
|
75
|
+
| `session.failed` | Mark the conversation failed. |
|
|
76
76
|
|
|
77
77
|
For the complete event table, see [Sessions, runs & streaming](../../concepts/sessions-runs-and-streaming).
|
|
78
78
|
|
|
79
|
+
When a submitted message includes attachments, `message.received.data.message` stays the
|
|
80
|
+
flattened compatibility summary, while `message.received.data.parts` carries renderable text and
|
|
81
|
+
file metadata. File parts never include raw bytes or internal sandbox paths; `url` appears only for
|
|
82
|
+
client-resolvable `http(s)` and `data:` URLs.
|
|
83
|
+
|
|
79
84
|
## Authorization pauses
|
|
80
85
|
|
|
81
86
|
`authorization.required` is different from the normal `session.waiting` boundary. It means a connection needs OAuth or another authorization challenge before the parked turn can continue. Chat UIs should render the authorization prompt, disable ordinary text input for that session, and persist the event with the rest of the chat history.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Dynamic Workflows"
|
|
3
|
+
description: "The experimental Workflow tool: let the model orchestrate its own subagents from model-authored JavaScript as one durable step."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
The experimental `Workflow` tool lets the model write JavaScript that coordinates the agent's own subagents as a single durable step. The program can run them in sequence, feed one result into the next, fan out over a list, and combine the results. You enable the capability and the model decides and runs the orchestration.
|
|
7
|
+
|
|
8
|
+
A single turn can already call several subagents, and parallel tool calls dispatch concurrently. What a workflow adds is _programmatic_ coordination. The program decides how many subagents to run based on an earlier result, which output feeds which call, and how to combine everything. That is logic the model cannot express as a few one-off calls.
|
|
9
|
+
|
|
10
|
+
## Enable the Workflow tool
|
|
11
|
+
|
|
12
|
+
Re-export the opt-in marker as the default export of `agent/tools/workflow.ts`. The marker name carries the "experimental" warning, but the tool the model actually sees is named `Workflow`.
|
|
13
|
+
|
|
14
|
+
```ts title="agent/tools/workflow.ts"
|
|
15
|
+
export { ExperimentalWorkflow as default } from "eve/tools";
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Without that file, the `Workflow` tool stays off. It earns its keep only when the agent has subagents (or the built-in `agent`) worth coordinating:
|
|
19
|
+
|
|
20
|
+
```ts title="agent/subagents/analyst/agent.ts"
|
|
21
|
+
import { defineAgent } from "eve";
|
|
22
|
+
|
|
23
|
+
export default defineAgent({
|
|
24
|
+
description: "Analyzes one metric: queries, computes, writes a short finding.",
|
|
25
|
+
model: "anthropic/claude-opus-4.8",
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
When asked for a weekly business review, the model picks the metrics, runs one `analyst` per metric in parallel, and combines the findings. The program below is the kind of JavaScript the model authors. It fans `analyst` out over a runtime-decided list of metrics and merges the results:
|
|
30
|
+
|
|
31
|
+
```js
|
|
32
|
+
const metrics = ["revenue", "signups", "churn"];
|
|
33
|
+
const findings = await Promise.all(
|
|
34
|
+
metrics.map((metric) => tools.analyst({ message: `Summarize last week's ${metric}.` })),
|
|
35
|
+
);
|
|
36
|
+
return findings.join("\n\n");
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Each `tools.analyst(...)` call dispatches a child subagent, so the parent stream records one `subagent.called` per metric and one `subagent.completed` as each finishes:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{ "type": "subagent.called", "data": { "name": "analyst", "toolName": "analyst", "callId": "call_1", "childSessionId": "ses_a1", "sequence": 0 } }
|
|
43
|
+
{ "type": "subagent.called", "data": { "name": "analyst", "toolName": "analyst", "callId": "call_2", "childSessionId": "ses_a2", "sequence": 1 } }
|
|
44
|
+
{ "type": "subagent.called", "data": { "name": "analyst", "toolName": "analyst", "callId": "call_3", "childSessionId": "ses_a3", "sequence": 2 } }
|
|
45
|
+
{ "type": "subagent.completed", "data": { "subagentName": "analyst", "callId": "call_1", "output": "..." } }
|
|
46
|
+
{ "type": "subagent.completed", "data": { "subagentName": "analyst", "callId": "call_2", "output": "..." } }
|
|
47
|
+
{ "type": "subagent.completed", "data": { "subagentName": "analyst", "callId": "call_3", "output": "..." } }
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## What a workflow can orchestrate
|
|
51
|
+
|
|
52
|
+
A workflow reaches only this agent's own agents: the built-in `agent` (a copy of itself), declared [subagents](../subagents), and [remote agents](./remote-agents). That is the whole list. No files, network, shell, skills, or connections. A workflow is a coordination layer over subagents, not a place to do other work. Each call can still request structured output via `outputSchema`, exactly like a direct subagent delegation.
|
|
53
|
+
|
|
54
|
+
## Caps on workflow-spawned subagents
|
|
55
|
+
|
|
56
|
+
Workflow orchestration is capped in two independent ways.
|
|
57
|
+
|
|
58
|
+
**Per-program call budget.** One Workflow program may dispatch at most `limits.maxSubagents` subagent calls in total, counted across the whole program — sequential and parallel calls alike. The default is 100. Calls beyond the budget do not start a child session; they resolve inside the program with a `WORKFLOW_SUBAGENT_LIMIT_REACHED` error result, and the budget is stated in the tool's description so the model sizes its fan-out to fit.
|
|
59
|
+
|
|
60
|
+
```ts title="agent/agent.ts"
|
|
61
|
+
export default defineAgent({
|
|
62
|
+
model: "anthropic/claude-sonnet-5",
|
|
63
|
+
limits: {
|
|
64
|
+
maxSubagents: 4,
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Root-only, one level of orchestration.** Only the root session ever sees the `Workflow` tool. The subagents a workflow spawns are ordinary delegated child sessions: they never receive the `Workflow` tool themselves, so a workflow cannot recursively spawn more workflows. Direct (non-workflow) delegation by those children stays subject to the usual `limits.maxSubagentDepth` cap (see [Subagents](../subagents)).
|
|
70
|
+
|
|
71
|
+
## Where the JavaScript runs
|
|
72
|
+
|
|
73
|
+
The orchestration code never touches the agent's process. The runtime hands the program text to a small isolated JavaScript engine (a QuickJS sandbox) and runs it there. Nothing from the host realm crosses in, so there is no `process`, no `globalThis` from the agent, and no `import`/`require`. The program can reach exactly two things, the agent functions bridged in as `tools.<name>` and the ordinary language built-ins.
|
|
74
|
+
|
|
75
|
+
That is an allowlist, not a denylist. The sandbox cannot read files, open a socket, or see an environment variable because those are not present, not because each one is blocked in turn. When the program calls an agent function, that call bridges back out to the runtime, which dispatches it exactly like a direct delegation. The orchestration glue stays inside the sandbox.
|
|
76
|
+
|
|
77
|
+
## Durability, approvals, and observability
|
|
78
|
+
|
|
79
|
+
- **Durable.** The whole orchestration counts as one step. Subagents dispatched together run concurrently, and if a run parks (suspends durably without holding compute; see [Execution model & durability](../concepts/execution-model-and-durability)) on a long-running or human-gated child, it resumes where it left off after a restart.
|
|
80
|
+
- **Approval-safe.** A subagent that needs human approval (HITL, human-in-the-loop) mid-run surfaces its request to the user, and the workflow picks back up once that is answered, same as direct delegation.
|
|
81
|
+
- **Observable.** Every orchestrated subagent emits the usual `subagent.called` / `subagent.completed` events on the parent stream and gets its own child session and stream. The telemetry matches direct delegation, so existing dashboards and cost attribution keep working.
|
|
82
|
+
|
|
83
|
+
## What to read next
|
|
84
|
+
|
|
85
|
+
- Declare the subagents a workflow orchestrates → [Subagents](../subagents)
|
|
86
|
+
- Call another deployment as one of those agents → [Remote agents](./remote-agents)
|
|
87
|
+
- The `agent/tools/` opt-in mechanism → [Default harness](../concepts/default-harness)
|
|
@@ -74,7 +74,7 @@ export function Chat() {
|
|
|
74
74
|
|
|
75
75
|
Most chat UIs only need `data.messages` and `status`. Drop down to `events` when you need the authoritative wire events directly, for example to persist an audit log or build a custom projection.
|
|
76
76
|
|
|
77
|
-
`data.messages` are `EveMessage[]` following the AI SDK `UIMessage` convention, so they drop straight into any AI SDK UI primitive that accepts a `UIMessage[]`. Parts include user text, assistant text, reasoning, tool calls, tool results, input requests, and connection authorization prompts.
|
|
77
|
+
`data.messages` are `EveMessage[]` following the AI SDK `UIMessage` convention, so they drop straight into any AI SDK UI primitive that accepts a `UIMessage[]`. Parts include user text, user file attachments, assistant text, reasoning, tool calls, tool results, input requests, and connection authorization prompts.
|
|
78
78
|
|
|
79
79
|
## Sending and streaming
|
|
80
80
|
|
|
@@ -98,6 +98,10 @@ await agent.send({
|
|
|
98
98
|
|
|
99
99
|
Assistant text, reasoning, tool calls, and tool results stream into `data` as they arrive, and `status` moves from `ready` to `submitted` to `streaming` and back. Call `stop()` to abort the active request, and `reset()` to clear local state so the next send starts a fresh durable session.
|
|
100
100
|
|
|
101
|
+
After eve confirms an attachment turn with `message.received`, the default reducer projects each
|
|
102
|
+
received attachment as a `file` part on the user message. The part includes `mediaType`, optional
|
|
103
|
+
`filename` and `size`, and a `url` only when the original attachment was browser-resolvable.
|
|
104
|
+
|
|
101
105
|
## Human-in-the-loop prompts
|
|
102
106
|
|
|
103
107
|
Tools opt into approval with `approval`, and the model can also ask a question with `ask_question` — see [Human-in-the-loop](/docs/human-in-the-loop) for the server-side model. Either way the stream emits an `input.requested` event, and the pending request rides on a `dynamic-tool` part of the latest message at `part.toolMetadata?.eve?.inputRequest`. Read it, then answer through the same session with `send()`:
|
package/docs/guides/meta.json
CHANGED
|
@@ -60,4 +60,5 @@ Both failure paths surface to the parent as a failed tool result, so the caller
|
|
|
60
60
|
## What to read next
|
|
61
61
|
|
|
62
62
|
- Local delegation and the isolation boundary → [Subagents](../subagents)
|
|
63
|
+
- Have the model orchestrate remote agents programmatically → [Dynamic workflows](./dynamic-workflows)
|
|
63
64
|
- Securing the receiving deployment → [Auth & route protection](./auth-and-route-protection)
|
|
@@ -54,7 +54,7 @@ The Subagents column states whether a local subagent (`subagents/<id>/`) can aut
|
|
|
54
54
|
| `channels/` | HTTP / messaging entrypoints | No | Root-only. |
|
|
55
55
|
| `connections/` | External service connections (MCP, OpenAPI) | Yes | One connection per file; name derived from filename. |
|
|
56
56
|
| `hooks/` | Lifecycle and stream-event subscribers | Yes | Module-backed only. Recursive directories supported. |
|
|
57
|
-
| `skills/` | On-demand procedures and capability packs | Yes | Flat markdown, module-backed skills, or packaged skills. Seeded into `/workspace/skills
|
|
57
|
+
| `skills/` | On-demand procedures and capability packs | Yes | Flat markdown, module-backed skills, or packaged skills. Seeded into `$HOME/.agents/skills/...`, with `/workspace/skills/...` as a fallback if `$HOME` is unavailable. |
|
|
58
58
|
| `lib/` | Shared authored helper code | Yes | Import-only; not mounted into the workspace. |
|
|
59
59
|
| `sandbox.ts` or `sandbox/sandbox.ts` | The agent's single sandbox | Yes | Use top-level `sandbox.ts` for a definition-only override; use `sandbox/sandbox.ts` + `sandbox/workspace/**` to also seed files. Framework default applies when neither is authored. |
|
|
60
60
|
| `sandbox/workspace/**` | Files seeded into the sandbox | Yes | Mirrored into `/workspace/...` at session bootstrap. |
|
|
@@ -62,13 +62,14 @@ The Subagents column states whether a local subagent (`subagents/<id>/`) can aut
|
|
|
62
62
|
| `schedules/` | Recurring jobs | No | Each schedule is `<name>.ts` (default-exported `defineSchedule`) or `<name>.md` (frontmatter `cron:` + prompt body). Recursive nesting supported. Root-only. |
|
|
63
63
|
| `subagents/` | Specialist child agents | Yes | Each child is its own local package under `subagents/<id>/`. Nested subagents are supported. |
|
|
64
64
|
|
|
65
|
-
## What reaches the runtime
|
|
65
|
+
## What reaches the runtime sandbox
|
|
66
66
|
|
|
67
|
-
eve does not mount the whole tree.
|
|
67
|
+
eve does not mount the whole tree. Authored workspace files land in the sandbox workspace:
|
|
68
68
|
|
|
69
|
-
- `skills/` files → `/workspace/skills/...`
|
|
70
69
|
- `agent/sandbox/workspace/**` → `/workspace/...` at session bootstrap
|
|
71
70
|
|
|
71
|
+
Skill files land outside the workspace, under `$HOME/.agents/skills/...`. If `$HOME` is unavailable, eve falls back to `/workspace/skills/...`. Packaged skill references such as `references/checklist.md` resolve relative to the directory containing that skill's `SKILL.md`.
|
|
72
|
+
|
|
72
73
|
Everything in `lib/` stays import-only source code and never reaches the workspace.
|
|
73
74
|
|
|
74
75
|
## Local subagent layout
|
|
@@ -52,7 +52,7 @@ export default defineTool({
|
|
|
52
52
|
| `mockModel` | `eve/evals` | Deterministic fixture agent models | [Evals](../evals/overview) |
|
|
53
53
|
| `useEveAgent` | `eve/react`, `eve/vue`, `eve/svelte` | frontend | [Frontend](../guides/frontend/overview) |
|
|
54
54
|
|
|
55
|
-
A few non-`define*` helpers round out the set: `disableTool` from `eve/tools` (see [Default harness](../concepts/default-harness)), the route verbs `GET`/`POST`/`PUT`/`PATCH`/`DELETE`/`WS` from `eve/channels`, the approval policies `always`/`once`/`never` from `eve/tools/approval`, and the channel auth helpers `localDev`/`vercelOidc`/`placeholderAuth` from `eve/channels/auth`. To wrap a built-in tool, import its default value from `eve/tools/defaults` (`bash`, `readFile`, `writeFile`, `glob`, `grep`, `webFetch`, `webSearch`, `todo`, `loadSkill`). `AgentReasoningDefinition` is exported from `eve` for the top-level `defineAgent({ reasoning })` setting. `AgentLimitsDefinition` is exported for `defineAgent({ limits })`. `AgentWorkflowDefinition` and `AgentWorkflowWorldDefinition` are exported from `eve` for the `defineAgent({ experimental: { workflow } })` config shape.
|
|
55
|
+
A few non-`define*` helpers round out the set: `disableTool` and `ExperimentalWorkflow` from `eve/tools` (see [Default harness](../concepts/default-harness)), the route verbs `GET`/`POST`/`PUT`/`PATCH`/`DELETE`/`WS` from `eve/channels`, the approval policies `always`/`once`/`never` from `eve/tools/approval`, and the channel auth helpers `localDev`/`vercelOidc`/`placeholderAuth` from `eve/channels/auth`. To wrap a built-in tool, import its default value from `eve/tools/defaults` (`bash`, `readFile`, `writeFile`, `glob`, `grep`, `webFetch`, `webSearch`, `todo`, `loadSkill`). `AgentReasoningDefinition` is exported from `eve` for the top-level `defineAgent({ reasoning })` setting. `AgentLimitsDefinition` is exported for `defineAgent({ limits })`. `AgentWorkflowDefinition` and `AgentWorkflowWorldDefinition` are exported from `eve` for the `defineAgent({ experimental: { workflow } })` config shape.
|
|
56
56
|
|
|
57
57
|
## Runtime context (`ctx`)
|
|
58
58
|
|
|
@@ -68,31 +68,31 @@ A few non-`define*` helpers round out the set: `disableTool` from `eve/tools` (s
|
|
|
68
68
|
|
|
69
69
|
## Imports at a glance
|
|
70
70
|
|
|
71
|
-
| Import | Holds
|
|
72
|
-
| ----------------------------------------------------------- |
|
|
73
|
-
| `eve` | `defineAgent`, `defineRemoteAgent`, agent config types
|
|
74
|
-
| `eve/tools` | `defineTool`, `defineDynamic`, `disableTool`
|
|
75
|
-
| `eve/tools/defaults` | the built-in tools as plain values
|
|
76
|
-
| `eve/tools/approval` | `always`, `once`, `never`
|
|
77
|
-
| `eve/connections` | `defineMcpClientConnection`, `defineOpenAPIConnection`
|
|
78
|
-
| `eve/channels` | `defineChannel`, route verbs
|
|
79
|
-
| `eve/channels/eve` | `eveChannel`
|
|
80
|
-
| `eve/channels/auth` | `localDev`, `vercelOidc`, `placeholderAuth`
|
|
81
|
-
| `eve/channels/{slack,discord,teams,telegram,twilio,github}` | platform channel factories
|
|
82
|
-
| `eve/hooks` | `defineHook`
|
|
83
|
-
| `eve/schedules` | `defineSchedule`
|
|
84
|
-
| `eve/skills` | `defineSkill`, `defineDynamic`
|
|
85
|
-
| `eve/instructions` | `defineInstructions`, `defineDynamic`
|
|
86
|
-
| `eve/context` | `defineState`, session and state types
|
|
87
|
-
| `eve/sandbox` | `defineSandbox`, backends
|
|
88
|
-
| `eve/instrumentation` | `defineInstrumentation`, `isChannel`
|
|
89
|
-
| `eve/evals` | `defineEval`, `defineEvalConfig`, `mockModel`, eval types
|
|
90
|
-
| `eve/evals/expect` | `includes`, `equals`, `matches`, `similarity`
|
|
91
|
-
| `eve/evals/reporters` | `Braintrust`, `JUnit`, `EvalReporter`
|
|
92
|
-
| `eve/evals/loaders` | `loadJson`, `loadYaml`
|
|
93
|
-
| `eve/react`, `eve/vue`, `eve/svelte` | `useEveAgent`
|
|
94
|
-
| `eve/next`, `eve/nuxt`, `eve/sveltekit` | framework bundler plugins
|
|
95
|
-
| [`eve/client`](../guides/client/overview) | `Client`, `ClientSession`
|
|
71
|
+
| Import | Holds |
|
|
72
|
+
| ----------------------------------------------------------- | -------------------------------------------------------------------- |
|
|
73
|
+
| `eve` | `defineAgent`, `defineRemoteAgent`, agent config types |
|
|
74
|
+
| `eve/tools` | `defineTool`, `defineDynamic`, `disableTool`, `ExperimentalWorkflow` |
|
|
75
|
+
| `eve/tools/defaults` | the built-in tools as plain values |
|
|
76
|
+
| `eve/tools/approval` | `always`, `once`, `never` |
|
|
77
|
+
| `eve/connections` | `defineMcpClientConnection`, `defineOpenAPIConnection` |
|
|
78
|
+
| `eve/channels` | `defineChannel`, route verbs |
|
|
79
|
+
| `eve/channels/eve` | `eveChannel` |
|
|
80
|
+
| `eve/channels/auth` | `localDev`, `vercelOidc`, `placeholderAuth` |
|
|
81
|
+
| `eve/channels/{slack,discord,teams,telegram,twilio,github}` | platform channel factories |
|
|
82
|
+
| `eve/hooks` | `defineHook` |
|
|
83
|
+
| `eve/schedules` | `defineSchedule` |
|
|
84
|
+
| `eve/skills` | `defineSkill`, `defineDynamic` |
|
|
85
|
+
| `eve/instructions` | `defineInstructions`, `defineDynamic` |
|
|
86
|
+
| `eve/context` | `defineState`, session and state types |
|
|
87
|
+
| `eve/sandbox` | `defineSandbox`, backends |
|
|
88
|
+
| `eve/instrumentation` | `defineInstrumentation`, `isChannel` |
|
|
89
|
+
| `eve/evals` | `defineEval`, `defineEvalConfig`, `mockModel`, eval types |
|
|
90
|
+
| `eve/evals/expect` | `includes`, `equals`, `matches`, `similarity` |
|
|
91
|
+
| `eve/evals/reporters` | `Braintrust`, `JUnit`, `EvalReporter` |
|
|
92
|
+
| `eve/evals/loaders` | `loadJson`, `loadYaml` |
|
|
93
|
+
| `eve/react`, `eve/vue`, `eve/svelte` | `useEveAgent` |
|
|
94
|
+
| `eve/next`, `eve/nuxt`, `eve/sveltekit` | framework bundler plugins |
|
|
95
|
+
| [`eve/client`](../guides/client/overview) | `Client`, `ClientSession` |
|
|
96
96
|
|
|
97
97
|
Exported types ship from the same entrypoint as the helper they describe (for example `ToolDefinition` and `ToolContext` from `eve/tools`). For the exhaustive list, read `packages/eve/src/public/index.ts`.
|
|
98
98
|
|