eve 0.16.2 → 0.17.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 +18 -0
- package/dist/src/chunks/{use-eve-agent-BEOUv37s.js → use-eve-agent-Bh1NmXO9.js} +8 -5
- package/dist/src/chunks/{use-eve-agent-C25KOe9i.js → use-eve-agent-Dvy_Wjvq.js} +8 -5
- package/dist/src/cli/dev/tui/tui.d.ts +2 -0
- package/dist/src/cli/dev/tui/tui.js +1 -1
- package/dist/src/cli/dev/url-target.d.ts +14 -0
- package/dist/src/cli/dev/url-target.js +1 -0
- package/dist/src/cli/run.js +3 -3
- package/dist/src/client/client.js +1 -1
- package/dist/src/compiled/.vendor-stamp.json +3 -3
- package/dist/src/compiled/@workflow/core/classify-error.d.ts +15 -0
- package/dist/src/compiled/@workflow/core/index.js +2 -2
- package/dist/src/compiled/@workflow/core/runtime.js +27 -27
- package/dist/src/compiled/@workflow/core/serialization.d.ts +12 -3
- package/dist/src/compiled/@workflow/core/step/context-storage.d.ts +10 -0
- package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/workflow.js +1 -1
- package/dist/src/compiled/_chunks/workflow/{attribute-changes-DUxG-Gic.js → attribute-changes-zAifvEhb.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{resume-hook-CUCPW67D.js → resume-hook-C15uJ2ik.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/run-BJUPZ0Ni.js +1 -0
- package/dist/src/compiled/_chunks/workflow/{sleep-Dxuzj5to.js → sleep-C8B-TYir.js} +1 -1
- package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
- package/dist/src/execution/remote-agent-dispatch.js +1 -1
- package/dist/src/execution/subagent-invocation.d.ts +20 -5
- package/dist/src/execution/subagent-invocation.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/harness/types.d.ts +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/authored-definition/schema-backed.js +1 -1
- package/dist/src/internal/http/basic-auth.d.ts +1 -0
- package/dist/src/internal/http/basic-auth.js +1 -0
- package/dist/src/public/channels/telegram/api.d.ts +3 -0
- package/dist/src/public/channels/telegram/api.js +2 -2
- package/dist/src/public/channels/telegram/inbound.d.ts +2 -0
- package/dist/src/public/channels/telegram/inbound.js +1 -1
- package/dist/src/public/channels/telegram/index.js +1 -1
- package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
- package/dist/src/public/definitions/tool.d.ts +0 -33
- 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/services/dev-client/client-options.d.ts +5 -1
- package/dist/src/services/dev-client/client-options.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- 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/channels/telegram.mdx +2 -0
- package/docs/concepts/default-harness.md +0 -10
- package/docs/guides/dev-tui.md +7 -1
- package/docs/guides/meta.json +0 -1
- package/docs/guides/remote-agents.md +0 -1
- package/docs/reference/cli.md +10 -1
- package/docs/reference/typescript-api.md +26 -26
- package/docs/subagents.mdx +0 -1
- package/package.json +5 -5
- package/dist/src/compiled/_chunks/workflow/run-CVlF84yI.js +0 -1
- package/docs/guides/dynamic-workflows.md +0 -70
|
@@ -209,36 +209,3 @@ export declare function disableTool(): DisabledToolSentinel;
|
|
|
209
209
|
* produced by {@link disableTool}.
|
|
210
210
|
*/
|
|
211
211
|
export declare function isDisabledToolSentinel(value: unknown): value is DisabledToolSentinel;
|
|
212
|
-
/**
|
|
213
|
-
* Marker discriminator written into the {@link ExperimentalWorkflow} opt-in
|
|
214
|
-
* sentinel.
|
|
215
|
-
*/
|
|
216
|
-
declare const ENABLE_WORKFLOW_TOOL_SENTINEL_KIND = "eve:enable-workflow-tool";
|
|
217
|
-
/**
|
|
218
|
-
* Marker value re-exported as the default export of a file in `agent/tools/`
|
|
219
|
-
* (conventionally `agent/tools/workflow.ts`) to enable the framework `Workflow`
|
|
220
|
-
* orchestration tool. The tool is off unless this marker is present,
|
|
221
|
-
* mirroring the {@link disableTool} opt-out in reverse.
|
|
222
|
-
*/
|
|
223
|
-
export interface EnableWorkflowToolSentinel {
|
|
224
|
-
readonly kind: typeof ENABLE_WORKFLOW_TOOL_SENTINEL_KIND;
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Opt-in marker for the framework `Workflow` tool, an isolated JavaScript sandbox whose
|
|
228
|
-
* only callable operations are this agent's subagents and remote agents, for
|
|
229
|
-
* orchestrating them from model-authored JavaScript. Re-export it as the
|
|
230
|
-
* default export of `agent/tools/workflow.ts`:
|
|
231
|
-
*
|
|
232
|
-
* ```ts
|
|
233
|
-
* export { ExperimentalWorkflow as default } from "eve/tools";
|
|
234
|
-
* ```
|
|
235
|
-
*
|
|
236
|
-
* The capability is experimental. The resulting model-facing tool is still
|
|
237
|
-
* called `Workflow`.
|
|
238
|
-
*/
|
|
239
|
-
export declare const ExperimentalWorkflow: EnableWorkflowToolSentinel;
|
|
240
|
-
/**
|
|
241
|
-
* Type guard: returns whether `value` is the {@link ExperimentalWorkflow}
|
|
242
|
-
* opt-in sentinel.
|
|
243
|
-
*/
|
|
244
|
-
export declare function isEnableWorkflowToolSentinel(value: unknown): value is EnableWorkflowToolSentinel;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DYNAMIC_SENTINEL_KIND,TOOL_BRAND}from"#shared/dynamic-tool-definition.js";import{stampDefinitionKey}from"#public/tool-result-narrowing.js";function defineTool(e){if(e.auth!==void 0)throw Error(`defineTool: The "auth" field is no longer supported. Pass auth providers inline to ctx.getToken(provider) or ctx.requireAuth(provider).`);return Object.assign(e,{[TOOL_BRAND]:!0}),stampDefinitionKey(e,`tool:${e.description}`),e}function defineDynamic(t){let n={kind:DYNAMIC_SENTINEL_KIND,events:t.events};return stampDefinitionKey(n,`dynamic:${Object.keys(t.events).join(`,`)}`),n}const DISABLED_TOOL_SENTINEL_KIND=`eve:disabled-tool`;function disableTool(){return{kind:DISABLED_TOOL_SENTINEL_KIND}}function isDisabledToolSentinel(e){return typeof e==`object`&&!!e&&e.kind===DISABLED_TOOL_SENTINEL_KIND}
|
|
1
|
+
import{DYNAMIC_SENTINEL_KIND,TOOL_BRAND}from"#shared/dynamic-tool-definition.js";import{stampDefinitionKey}from"#public/tool-result-narrowing.js";function defineTool(e){if(e.auth!==void 0)throw Error(`defineTool: The "auth" field is no longer supported. Pass auth providers inline to ctx.getToken(provider) or ctx.requireAuth(provider).`);return Object.assign(e,{[TOOL_BRAND]:!0}),stampDefinitionKey(e,`tool:${e.description}`),e}function defineDynamic(t){let n={kind:DYNAMIC_SENTINEL_KIND,events:t.events};return stampDefinitionKey(n,`dynamic:${Object.keys(t.events).join(`,`)}`),n}const DISABLED_TOOL_SENTINEL_KIND=`eve:disabled-tool`;function disableTool(){return{kind:DISABLED_TOOL_SENTINEL_KIND}}function isDisabledToolSentinel(e){return typeof e==`object`&&!!e&&e.kind===DISABLED_TOOL_SENTINEL_KIND}export{defineDynamic,defineTool,disableTool,isDisabledToolSentinel};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tool authoring helpers for `agent/tools/*.ts` files.
|
|
3
3
|
*/
|
|
4
|
-
export { type DisabledToolSentinel,
|
|
4
|
+
export { type DisabledToolSentinel, defineDynamic, defineTool, disableTool, isDisabledToolSentinel, type ToolAuthOptions, type ToolAuthProvider, type ToolDefinition, type ToolContext, type ToolModelOutput, } from "#public/definitions/tool.js";
|
|
5
5
|
export type { Approval, ApprovalContext, ApprovalStatus } from "#public/definitions/approval.js";
|
|
6
6
|
export type { DynamicToolEntry, DynamicEvents, DynamicToolEvents, DynamicResolveContext, DynamicSentinel, DynamicToolSet, DynamicToolResult, } from "#shared/dynamic-tool-definition.js";
|
|
7
7
|
export { type SessionContext } from "#public/definitions/callback-context.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{defineDynamic,defineTool,disableTool,isDisabledToolSentinel}from"#public/definitions/tool.js";import{toolResultFrom}from"#public/tool-result-narrowing.js";import{defineBashTool}from"#public/tools/define-bash-tool.js";import{defineGlobTool}from"#public/tools/define-glob-tool.js";import{defineGrepTool}from"#public/tools/define-grep-tool.js";import{defineReadFileTool}from"#public/tools/define-read-file-tool.js";import{defineWriteFileTool}from"#public/tools/define-write-file-tool.js";export{defineBashTool,defineDynamic,defineGlobTool,defineGrepTool,defineReadFileTool,defineTool,defineWriteFileTool,disableTool,isDisabledToolSentinel,toolResultFrom};
|
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import type { ClientOptions } from "#client/index.js";
|
|
2
2
|
import type { DevelopmentCredentialGate } from "./credential-gate.js";
|
|
3
|
+
type DevelopmentClientHeaders = Readonly<Record<string, string>>;
|
|
3
4
|
/**
|
|
4
5
|
* Builds anonymous {@link ClientOptions} for a development target. Locality is
|
|
5
6
|
* not an authorization decision, so remote URLs receive no ambient Vercel
|
|
6
7
|
* credentials through this default path.
|
|
7
8
|
*/
|
|
8
9
|
export declare function resolveDevelopmentClientOptions(serverUrl: string): ClientOptions;
|
|
9
|
-
/** Builds a non-redirecting local client
|
|
10
|
+
/** Builds a non-redirecting local client, using ambient bearer auth only when it owns Authorization. */
|
|
10
11
|
export declare function resolveLocalDevelopmentClientOptions(input: {
|
|
12
|
+
readonly headers?: DevelopmentClientHeaders;
|
|
11
13
|
readonly serverUrl: string;
|
|
12
14
|
readonly token: () => Promise<string>;
|
|
13
15
|
}): ClientOptions;
|
|
14
16
|
/** Builds non-redirecting client options backed by one verified credential gate. */
|
|
15
17
|
export declare function resolveRemoteDevelopmentClientOptions(input: {
|
|
16
18
|
readonly credentials: DevelopmentCredentialGate;
|
|
19
|
+
readonly headers?: DevelopmentClientHeaders;
|
|
17
20
|
readonly serverUrl: string;
|
|
18
21
|
}): ClientOptions;
|
|
22
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function resolveDevelopmentClientOptions(e){return{host:e}}function resolveLocalDevelopmentClientOptions(e){return{auth:{bearer:e.token},
|
|
1
|
+
import{VERCEL_TRUSTED_OIDC_IDP_TOKEN_HEADER}from"#client/types.js";function hasAuthorizationHeader(e){return e!==void 0&&Object.keys(e).some(e=>e.toLowerCase()===`authorization`)}async function resolveRemoteHeaders(t){if(!t.includeTrustedOidcHeader)return{...await t.credentials.resolveBypassHeaders(),...t.headers};let[n,r]=await Promise.all([t.credentials.resolveBypassHeaders(),t.credentials.resolveToken()]),i={...n,...t.headers},a=r.trim();return a.length>0&&(i[VERCEL_TRUSTED_OIDC_IDP_TOKEN_HEADER]=a),i}function resolveDevelopmentClientOptions(e){return{host:e}}function resolveLocalDevelopmentClientOptions(e){let t={host:e.serverUrl,redirect:`manual`};if(hasAuthorizationHeader(e.headers))return{...t,headers:e.headers};let n={...t,auth:{bearer:e.token}};return e.headers===void 0?n:{...n,headers:e.headers}}function resolveRemoteDevelopmentClientOptions(e){let t=new URL(e.serverUrl).origin;if(e.credentials.serverOrigin!==t)throw Error(`Credential gate origin ${e.credentials.serverOrigin} does not match client origin ${t}.`);return hasAuthorizationHeader(e.headers)?{headers:()=>resolveRemoteHeaders({credentials:e.credentials,headers:e.headers,includeTrustedOidcHeader:!0}),host:e.serverUrl,redirect:`manual`}:{auth:{vercelOidc:{token:()=>e.credentials.resolveToken()}},headers:e.headers===void 0?e.credentials.resolveBypassHeaders:()=>resolveRemoteHeaders({credentials:e.credentials,headers:e.headers,includeTrustedOidcHeader:!1}),host:e.serverUrl,redirect:`manual`}}export{resolveDevelopmentClientOptions,resolveLocalDevelopmentClientOptions,resolveRemoteDevelopmentClientOptions};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{pinnedNodeEngineMajor}from"../../node-engine.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{basename,join,resolve}from"node:path";import{mkdir,readdir,stat}from"node:fs/promises";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),DEFAULT_AI_PACKAGE_VERSION=`^7.0.0`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.2.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.
|
|
1
|
+
import{pinnedNodeEngineMajor}from"../../node-engine.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{basename,join,resolve}from"node:path";import{mkdir,readdir,stat}from"node:fs/promises";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),DEFAULT_AI_PACKAGE_VERSION=`^7.0.0`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.2.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.17.1`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
|
|
2
2
|
|
|
3
3
|
export default defineAgent({
|
|
4
4
|
model: "__EVE_INIT_MODEL__",
|
package/dist/src/svelte/index.js
CHANGED
package/dist/src/vue/index.js
CHANGED
|
@@ -53,6 +53,8 @@ Human-in-the-loop (HITL) turns option requests into inline-keyboard buttons and
|
|
|
53
53
|
|
|
54
54
|
Start a session without an inbound message through `receive(telegram, { message, target, auth })` from a schedule `run` handler, or `args.receive(telegram, ...)` from another channel. `target.chatId` is required. Add `messageThreadId` to land in a specific forum topic.
|
|
55
55
|
|
|
56
|
+
Private proactive chats stay keyed to the chat, or to the chat plus `messageThreadId` when you target a topic. Group and supergroup proactive sends anchor to the bot message id returned by Telegram, so replies to different bot messages can resume different sessions in the same chat. If Telegram does not return a recognized chat type for an outbound send, eve keeps the session unanchored instead of guessing.
|
|
57
|
+
|
|
56
58
|
### Attachments
|
|
57
59
|
|
|
58
60
|
Inbound photos and documents are supported. eve fetches them on demand via `getFile`, only when an upload policy allows the type:
|
|
@@ -87,16 +87,6 @@ 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. See [Dynamic workflows](../guides/dynamic-workflows).
|
|
99
|
-
|
|
100
90
|
## What to read next
|
|
101
91
|
|
|
102
92
|
- [Tools](../tools): define your own tools, gate them on approval, and shape their output with `toModelOutput`
|
package/docs/guides/dev-tui.md
CHANGED
|
@@ -128,7 +128,13 @@ Pass a URL and the TUI talks to a running deployment instead of starting a local
|
|
|
128
128
|
eve dev https://<your-app>
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
-
The bare URL is shorthand for `--url`; it cannot be combined with `--host`, `--port`, or `--no-ui`.
|
|
131
|
+
The bare URL is shorthand for `--url`; it cannot be combined with `--host`, `--port`, or `--no-ui`. For HTTP Basic auth, put credentials in the URL; eve sends them as a Basic `Authorization` header and strips them from the server URL before connecting:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
eve dev https://user:pass@<your-app>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
For bearer tokens or custom schemes, repeat `-H, --header` to attach request headers.
|
|
132
138
|
|
|
133
139
|
At startup the TUI asks Vercel to resolve the remote origin under the active scope. A resolved response is the authority for a project-scoped OIDC token—refreshing an expired development token when refresh credentials exist—or an automation-bypass secret. An unresolved host is probed anonymously. The TUI then requests `/eve/v1/info`, with a ten-second timeout. A successful response marks the remote ready. An eve OIDC challenge, Vercel Deployment Protection challenge, or `TRUSTED_SOURCES_ENVIRONMENT_MISMATCH` opens `/vc:login` automatically; ordinary network failures and server errors remain remote-availability errors and do not start an authentication flow. Esc or Ctrl-C cancels the authentication flow.
|
|
134
140
|
|
package/docs/guides/meta.json
CHANGED
|
@@ -60,5 +60,4 @@ 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)
|
|
64
63
|
- Securing the receiving deployment → [Auth & route protection](./auth-and-route-protection)
|
package/docs/reference/cli.md
CHANGED
|
@@ -91,13 +91,14 @@ eve dev [options]
|
|
|
91
91
|
eve dev https://your-app.vercel.app
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
Pass a bare URL
|
|
94
|
+
Pass a bare URL and the UI connects to that server instead of booting a local one (same as `--url`), which lets you smoke-test a preview or production deployment. The interactive UI turns off in a non-TTY terminal.
|
|
95
95
|
|
|
96
96
|
| Flag | Type | Default | Description |
|
|
97
97
|
| ----------------------------------- | ------ | ------------------ | ----------------------------------------------------------------------------------------- |
|
|
98
98
|
| `--host <host>` | string | all interfaces | Host interface to bind |
|
|
99
99
|
| `--port <port>` | number | `$PORT`, then 3000 | Port to listen on |
|
|
100
100
|
| `-u, --url <url>` | string | none | Connect to an existing server URL instead of starting one |
|
|
101
|
+
| `-H, --header <header>` | string | none | Request header for a URL target, in `Name: value` form; repeat for multiple headers |
|
|
101
102
|
| `--no-ui` | flag | UI on | Start the server without an interactive UI |
|
|
102
103
|
| `--name <name>` | string | app folder name | Title shown in the terminal UI |
|
|
103
104
|
| `--input <text>` | string | none | Pre-fill the prompt input; bare local `/model` starts onboarding |
|
|
@@ -111,6 +112,14 @@ Pass a bare URL as the only argument and the UI connects to that server instead
|
|
|
111
112
|
|
|
112
113
|
A fresh `eve init` passes `--input /model`. That bare local input starts onboarding: the TUI installs the Vercel CLI if needed, asks you to log in if needed, then opens `/model`. Other input stays editable in the prompt.
|
|
113
114
|
|
|
115
|
+
For a URL target protected by HTTP Basic auth, put the credentials in the URL. Eve sends them as a Basic `Authorization` header and strips them from the server URL before connecting:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
eve dev https://user:pass@your-app.example.com
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
For bearer tokens or custom schemes, pass explicit headers with `-H`.
|
|
122
|
+
|
|
114
123
|
Local dev records the last ready URL per resolved app root in `.eve/dev-server-state.v1.json`. A second interactive `eve dev` reconnects only when that URL is loopback and healthy; each terminal UI creates a fresh client session while sharing the server process. A stale or malformed record is replaced when eve starts a new server. Passing `--host`, `--port`, or a `PORT` environment value skips reconnection and reports a healthy recorded server instead.
|
|
115
124
|
|
|
116
125
|
Local dev keeps immutable runtime source snapshots under `.eve/dev-runtime/snapshots/` so in-flight sessions hold a consistent code revision while new prompts pick up rebuilds. On startup, `eve dev` prunes stale runtime snapshots and old local sandbox templates in the background. For manual cleanup, stop `eve dev` and delete `.eve/dev-runtime/snapshots/` or `.eve/sandbox-cache/local/templates/`.
|
|
@@ -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`
|
|
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. `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` and `ExperimentalWo
|
|
|
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` |
|
|
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
|
|
package/docs/subagents.mdx
CHANGED
|
@@ -99,4 +99,3 @@ Split out a subagent when the task needs a different prompt or specialist role,
|
|
|
99
99
|
## What to read next
|
|
100
100
|
|
|
101
101
|
- [Remote agents](./guides/remote-agents): call another eve deployment as a subagent.
|
|
102
|
-
- [Dynamic workflows](./guides/dynamic-workflows): have the model orchestrate its subagents programmatically (fan-out, map-reduce).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eve",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
|
|
6
6
|
"keywords": [
|
|
@@ -287,11 +287,11 @@
|
|
|
287
287
|
"@vercel/oidc": "3.5.0",
|
|
288
288
|
"@vercel/sandbox": "2.2.1",
|
|
289
289
|
"@vercel/sdk": "1.28.1",
|
|
290
|
-
"@workflow/core": "5.0.0-beta.
|
|
290
|
+
"@workflow/core": "5.0.0-beta.26",
|
|
291
291
|
"@workflow/errors": "5.0.0-beta.8",
|
|
292
|
-
"@workflow/serde": "
|
|
293
|
-
"@workflow/world": "5.0.0-beta.
|
|
294
|
-
"@workflow/world-local": "5.0.0-beta.
|
|
292
|
+
"@workflow/serde": "5.0.0-beta.2",
|
|
293
|
+
"@workflow/world": "5.0.0-beta.14",
|
|
294
|
+
"@workflow/world-local": "5.0.0-beta.22",
|
|
295
295
|
"ai": "^7.0.0",
|
|
296
296
|
"autoevals": "0.0.132",
|
|
297
297
|
"chat": "4.31.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{d as e}from"./dist-FLIfyJ4Y.js";import{C as t,S as n,T as r,b as i,m as a,r as o,w as s,x as c}from"./dist-Dxrjttr2.js";import{A as l,At as u,C as d,Dn as f,Gt as p,It as m,J as h,L as g,Lt as _,Q as v,T as y,Wt as b,Y as x,_n as S,a as C,b as w,en as T,gn as E,hn as D,k as O,kn as k,m as A,n as j,p as M,r as N,s as P,t as F,xn as I,z as L}from"./attribute-changes-DUxG-Gic.js";const R=f();let z=!1;async function B(t,n,r){"use step";return await N(()=>{let i=t?.workflowId;if(!i)throw new s(`'start' received an invalid workflow function. Ensure the Workflow SDK is configured correctly and the function includes a 'use workflow' directive.`,{slug:`start-invalid-workflow-function`});return x(`workflow.start ${e(i)}`,async e=>{e?.setAttributes({...m(i),..._(`start`)});let t=[],a=r??{};Array.isArray(n)?t=n:typeof n==`object`&&(a=n),e?.setAttributes({...u(t.length)});let c=a?.world??await S(),l=await c.getDeploymentId(),d=a.deploymentId??l;d===`latest`&&(c.resolveLatestDeploymentId?d=await c.resolveLatestDeploymentId():(z||(z=!0,L.warn(`deploymentId: 'latest' has no effect in this world and was ignored. It is only supported by worlds with atomic deployments, such as Vercel. The run will target the current deployment.`,{currentDeploymentId:l})),d=l));let f,g;if(d===l)f=!0,g=!0;else if(typeof c.streams?.get!=`function`)f=!1,g=!1;else{let e=A((await P(c,`workflow`,{deploymentId:d,timeout:2e3}).catch(()=>void 0))?.workflowCoreVersion);f=e.framedByteStreams,g=e.supportedFormats.has(T.GZIP)}let y=[],x=`wrun_${R()}`,E=await h(),D=a.specVersion??c.specVersion??2,O=k(D),N=a.allowReservedAttributes===!0,B;if(a.attributes&&Object.keys(a.attributes).length>0){if(D<4)throw new s(`Initial workflow attributes require a World that supports spec version 4 or later.`);for(let[e,t]of Object.entries(a.attributes))if(typeof t!=`string`)throw new s(`Initial workflow attribute ${JSON.stringify(e)} must be a string value.`);let e=F(a.attributes,{allowReservedAttributes:N});B=Object.fromEntries(e.map(({key:e,value:t})=>[e,t]))}let H=B?{attributes:B,...N?{allowReservedAttributes:!0}:{}}:{},U=await c.getEncryptionKeyForRun?.(x,{...a,deploymentId:d}),W=U?await I(U):void 0,G=await w(t,x,W,y,globalThis,O,f,g&&D>=5),K={traceCarrier:E,workflowCoreVersion:M,features:{encryption:!!W}},[q,J]=await Promise.allSettled([c.events.create(x,{eventType:`run_created`,specVersion:D,eventData:{deploymentId:d,workflowName:i,input:G,executionContext:K,...H}},{v1Compat:O}),c.queue(C(i),{runId:x,traceCarrier:E,...D>=3?{runInput:{input:G,deploymentId:d,workflowName:i,specVersion:D,executionContext:K,...H}}:{}},{deploymentId:d,specVersion:D})]);if(J.status===`rejected`)throw J.reason;let X=!1;if(q.status===`rejected`){let e=q.reason;if(!o.is(e))if(V(e))X=!0,L.warn(`Run creation event failed, but the run was accepted via the queue. The run_created event will be re-tried async by the runtime.`,{workflowRunId:x,error:e.message});else throw e}else{let e=q.value;if(!e.run)throw new s(`Missing 'run' in server response for 'run_created' event`);if(!O&&e.run.runId!==x)throw new s(`Server returned different runId than requested: expected ${x}, got ${e.run.runId}`)}return j(Promise.all(y),e=>{L.warn(`Background flush of workflow argument streams failed`,{workflowRunId:x,error:e instanceof Error?e.message:String(e)})}),e?.setAttributes({...b(x),...v(d),...q.status===`fulfilled`&&q.value.run?p(q.value.run.status):{}}),new Y(x,{resilientStart:X})})})}function V(e){return!!(a.is(e)||r.is(e)&&e.status&&e.status>=500)}const H=e=>Array.isArray(e)?e:[e];async function U(e,t,n={}){try{let r=await e.runs.get(t,{resolveData:`all`}),i=await e.getEncryptionKeyForRun?.(r),a=i?await I(i):void 0,o=H(await O(r.input,t,a,globalThis)),s=n.specVersion??r.specVersion??1,c=n.deploymentId??r.deploymentId;return(await B({workflowId:r.workflowName},o,{deploymentId:c,world:e,specVersion:s})).runId}catch(e){throw Error(`Failed to recreate run from ${t}: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}async function W(e,t){try{let n=(await e.runs.get(t,{resolveData:`none`})).specVersion??1,r=k(n),i={eventType:`run_cancelled`,specVersion:n};await e.events.create(t,i,{v1Compat:r})}catch(e){throw Error(`Failed to cancel run ${t}: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}async function G(e,t){try{let n=await e.runs.get(t,{resolveData:`none`});await e.queue(C(n.workflowName),{runId:t},{deploymentId:n.deploymentId,specVersion:n.specVersion??1})}catch(e){throw Error(`Failed to re-enqueue run ${t}: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}async function K(e,t,n){try{let r=await e.runs.get(t,{resolveData:`none`}),i=k(r.specVersion),a=[],s=null;do{let n=await e.events.list({runId:t,pagination:{limit:1e3,...s?{cursor:s}:{}},resolveData:`none`});a.push(...n.data),s=n.hasMore?n.cursor:null}while(s);let c=a.filter(e=>e.eventType===`wait_created`),l=new Set(a.filter(e=>e.eventType===`wait_completed`).map(e=>e.correlationId)),u=c.filter(e=>!l.has(e.correlationId));if(n?.correlationIds&&n.correlationIds.length>0){let e=new Set(n.correlationIds);u=u.filter(t=>t.correlationId&&e.has(t.correlationId))}let d=[],f=0;for(let n of u){if(!n.correlationId)continue;let a=i?{eventType:`wait_completed`,correlationId:n.correlationId}:{eventType:`wait_completed`,correlationId:n.correlationId,specVersion:r.specVersion,eventData:{resumeAt:n.eventData.resumeAt}};try{await e.events.create(t,a,{v1Compat:i}),f++}catch(e){o.is(e)?f++:d.push(e instanceof Error?e:Error(String(e)))}}if(f>0&&await e.queue(C(r.workflowName),{runId:t},{deploymentId:r.deploymentId,specVersion:r.specVersion??1}),d.length>0)throw AggregateError(d,`Failed to complete ${d.length}/${u.length} pending wait(s) for run ${t}`);return{stoppedCount:f}}catch(e){throw e instanceof AggregateError?e:Error(`Failed to wake up run ${t}: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}async function q(e,t,n,r){try{return await e.streams.get(t,n,r?.startIndex)}catch(e){throw Error(`Failed to read stream ${n}: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}async function J(e,t){try{return await e.streams.list(t)}catch(e){throw Error(`Failed to list streams for run ${t}: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}var Y=class e{static[E](e){return{runId:e.runId,resilientStart:e.#r}}static[D](t){return new e(t.runId,{resilientStart:t.resilientStart})}runId;#e;get#t(){return this.#e||=S(),this.#e}#n=null;#r=!1;constructor(e,t){this.runId=e,this.#r=t?.resilientStart??!1}#i(){return this.#n||=(async()=>{let e=await this.#t,t=await e.runs.get(this.runId),n=await e.getEncryptionKeyForRun?.(t);return n?await I(n):void 0})(),this.#n}#a(){return()=>this.#i()}async wakeUp(e){"use step";return K(await this.#t,this.runId,e)}async cancel(){"use step";await(await this.#t).events.create(this.runId,{eventType:`run_cancelled`,specVersion:5})}get exists(){"use step";return this.#t.then(e=>e.runs.get(this.runId,{resolveData:`none`}).then(()=>!0).catch(e=>{if(t.is(e))return!1;throw e}))}get status(){"use step";return this.#t.then(e=>e.runs.get(this.runId).then(e=>e.status))}get returnValue(){"use step";return this.#o()}get workflowName(){"use step";return this.#t.then(e=>e.runs.get(this.runId).then(e=>e.workflowName))}get createdAt(){"use step";return this.#t.then(e=>e.runs.get(this.runId).then(e=>e.createdAt))}get startedAt(){"use step";return this.#t.then(e=>e.runs.get(this.runId).then(e=>e.startedAt))}get completedAt(){"use step";return this.#t.then(e=>e.runs.get(this.runId).then(e=>e.completedAt))}get readable(){return this.getReadable()}getReadable(e={}){"use step";let{ops:t=[],global:n=globalThis,startIndex:r,namespace:i}=e,a=g(this.runId,i),o=this.#a(),s=d(n,t,this.runId,o).ReadableStream({name:a,startIndex:r}),c=this.#t,l=this.runId;return Object.assign(s,{getTailIndex:async()=>(await(await c).streams.getInfo(l,a)).tailIndex})}async#o(){let e=await this.#t,r=0,a=this.#r?3:0,o=[1e3,3e3,6e3];for(;;)try{let t=await e.runs.get(this.runId);if(t.status===`completed`){let e=await this.#i();return await l(t.output,this.runId,e)}if(t.status===`cancelled`)throw new i(this.runId);if(t.status===`failed`){let e=await this.#i(),n;try{n=await y(t.error,this.runId,e)}catch{n=Error(`Failed to hydrate workflow run error`)}throw new c(this.runId,n,{errorCode:t.errorCode})}throw new n(this.runId,t.status)}catch(e){if(n.is(e)){await new Promise(e=>setTimeout(e,1e3));continue}if(t.is(e)&&r<a){let e=o[r];r++,await new Promise(t=>setTimeout(t,e));continue}throw e}}};function X(e){return new Y(e)}export{q as a,K as c,J as i,B as l,X as n,U as o,W as r,G as s,Y as t};
|
|
@@ -1,70 +0,0 @@
|
|
|
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
|
-
## Where the JavaScript runs
|
|
55
|
-
|
|
56
|
-
The orchestration code never touches the agent's process. The runtime hands the program text to a small isolated JavaScript engine (a QuickJS sandbox) and runs it there. Nothing from the host realm crosses in, so there is no `process`, no `globalThis` from the agent, and no `import`/`require`. The program can reach exactly two things, the agent functions bridged in as `tools.<name>` and the ordinary language built-ins.
|
|
57
|
-
|
|
58
|
-
That is an allowlist, not a denylist. The sandbox cannot read files, open a socket, or see an environment variable because those are not present, not because each one is blocked in turn. When the program calls an agent function, that call bridges back out to the runtime, which dispatches it exactly like a direct delegation. The orchestration glue stays inside the sandbox.
|
|
59
|
-
|
|
60
|
-
## Durability, approvals, and observability
|
|
61
|
-
|
|
62
|
-
- **Durable.** The whole orchestration counts as one step. Subagents dispatched together run concurrently, and if a run parks (suspends durably without holding compute; see [Execution model & durability](../concepts/execution-model-and-durability)) on a long-running or human-gated child, it resumes where it left off after a restart.
|
|
63
|
-
- **Approval-safe.** A subagent that needs human approval (HITL, human-in-the-loop) mid-run surfaces its request to the user, and the workflow picks back up once that is answered, same as direct delegation.
|
|
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
|
-
|
|
66
|
-
## What to read next
|
|
67
|
-
|
|
68
|
-
- Declare the subagents a workflow orchestrates → [Subagents](../subagents)
|
|
69
|
-
- Call another deployment as one of those agents → [Remote agents](./remote-agents)
|
|
70
|
-
- The `agent/tools/` opt-in mechanism → [Default harness](../concepts/default-harness)
|