eve 0.13.7 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/src/channel/routes.d.ts +5 -0
  3. package/dist/src/channel/send.js +1 -1
  4. package/dist/src/channel/types.d.ts +5 -0
  5. package/dist/src/compiled/.vendor-stamp.json +12 -8
  6. package/dist/src/compiled/@ai-sdk/anthropic/index.d.ts +2 -2
  7. package/dist/src/compiled/@ai-sdk/anthropic/index.js +2 -2
  8. package/dist/src/compiled/@ai-sdk/google/index.d.ts +25 -3
  9. package/dist/src/compiled/@ai-sdk/google/index.js +6 -6
  10. package/dist/src/compiled/@ai-sdk/mcp/index.d.ts +647 -30
  11. package/dist/src/compiled/@ai-sdk/mcp/index.js +1 -1
  12. package/dist/src/compiled/@ai-sdk/openai/index.d.ts +8 -2
  13. package/dist/src/compiled/@ai-sdk/openai/index.js +2 -2
  14. package/dist/src/compiled/@ai-sdk/otel/index.d.ts +165 -28
  15. package/dist/src/compiled/@ai-sdk/otel/index.js +3 -3
  16. package/dist/src/compiled/@ai-sdk/provider/index.d.ts +10 -2
  17. package/dist/src/compiled/@ai-sdk/provider-utils/index.d.ts +2362 -0
  18. package/dist/src/compiled/@ai-sdk/provider-utils/index.js +1 -0
  19. package/dist/src/compiled/@workflow/serde/LICENSE.md +3 -0
  20. package/dist/src/compiled/@workflow/serde/index.d.ts +30 -0
  21. package/dist/src/compiled/@workflow/serde/index.js +1 -0
  22. package/dist/src/compiled/_chunks/workflow/{dist-C9PV_vnE.js → dist-D7CzPkf8.js} +1 -1
  23. package/dist/src/compiled/eventsource-parser/stream/LICENSE +21 -0
  24. package/dist/src/compiled/eventsource-parser/stream/index.d.ts +121 -0
  25. package/dist/src/compiled/eventsource-parser/stream/index.js +1 -0
  26. package/dist/src/compiled/experimental-ai-sdk-code-mode/approval-continuation.d.ts +7 -7
  27. package/dist/src/compiled/experimental-ai-sdk-code-mode/continuation-capability.d.ts +15 -4
  28. package/dist/src/compiled/experimental-ai-sdk-code-mode/index.d.ts +1 -1
  29. package/dist/src/compiled/experimental-ai-sdk-code-mode/index.js +15 -15
  30. package/dist/src/compiled/experimental-ai-sdk-code-mode/interrupt-continuation.d.ts +5 -5
  31. package/dist/src/compiled/experimental-ai-sdk-code-mode/runtime/protocol.d.ts +13 -2
  32. package/dist/src/compiled/experimental-ai-sdk-code-mode/types.d.ts +26 -0
  33. package/dist/src/compiled/json-schema/LICENSE +21 -0
  34. package/dist/src/compiled/json-schema/index.d.ts +749 -0
  35. package/dist/src/compiled/json-schema/index.js +1 -0
  36. package/dist/src/compiler/manifest.js +1 -1
  37. package/dist/src/compiler/normalize-agent-config.js +1 -1
  38. package/dist/src/context/build-dynamic-tools.js +1 -1
  39. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  40. package/dist/src/context/keys.d.ts +1 -1
  41. package/dist/src/execution/create-session-step.d.ts +0 -17
  42. package/dist/src/execution/create-session-step.js +1 -1
  43. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  44. package/dist/src/execution/dispatch-workflow-runtime-actions-step.d.ts +12 -0
  45. package/dist/src/execution/dispatch-workflow-runtime-actions-step.js +1 -0
  46. package/dist/src/execution/eve-workflow-attributes.d.ts +1 -1
  47. package/dist/src/execution/next-driver-action.d.ts +1 -1
  48. package/dist/src/execution/node-step.js +1 -1
  49. package/dist/src/execution/sandbox/prewarm.js +1 -1
  50. package/dist/src/execution/session.js +3 -3
  51. package/dist/src/execution/turn-workflow.js +1 -1
  52. package/dist/src/execution/workflow-entry.js +1 -1
  53. package/dist/src/execution/workflow-runtime.d.ts +2 -3
  54. package/dist/src/execution/workflow-runtime.js +1 -1
  55. package/dist/src/execution/workflow-steps.d.ts +1 -1
  56. package/dist/src/execution/workflow-steps.js +1 -1
  57. package/dist/src/harness/action-result-helpers.d.ts +2 -2
  58. package/dist/src/harness/emission.js +1 -1
  59. package/dist/src/harness/execute-tool.d.ts +2 -2
  60. package/dist/src/harness/input-extraction.js +1 -1
  61. package/dist/src/harness/tool-loop.js +1 -1
  62. package/dist/src/harness/tools.d.ts +4 -6
  63. package/dist/src/harness/tools.js +1 -1
  64. package/dist/src/harness/types.d.ts +4 -10
  65. package/dist/src/harness/workflow-continuation-security.d.ts +4 -0
  66. package/dist/src/harness/workflow-continuation-security.js +1 -0
  67. package/dist/src/harness/workflow-interrupt-state.d.ts +14 -0
  68. package/dist/src/harness/workflow-interrupt-state.js +1 -0
  69. package/dist/src/harness/workflow-lifecycle.d.ts +13 -0
  70. package/dist/src/harness/workflow-lifecycle.js +1 -0
  71. package/dist/src/harness/workflow-runtime-action-state.d.ts +9 -0
  72. package/dist/src/harness/workflow-runtime-action-state.js +1 -0
  73. package/dist/src/harness/workflow-sandbox.d.ts +22 -0
  74. package/dist/src/harness/workflow-sandbox.js +2 -0
  75. package/dist/src/harness/workflow-tool-description.d.ts +2 -2
  76. package/dist/src/harness/workflow-tool-description.js +16 -4
  77. package/dist/src/internal/application/package.js +1 -1
  78. package/dist/src/internal/authored-definition/connection.js +1 -1
  79. package/dist/src/internal/authored-definition/core.js +1 -1
  80. package/dist/src/internal/authored-definition/schema-backed.js +1 -1
  81. package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
  82. package/dist/src/internal/nitro/host/workflow-sandbox-runtime-plugin.d.ts +1 -0
  83. package/dist/src/internal/nitro/host/workflow-sandbox-runtime-plugin.js +1 -0
  84. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response-from-manifest.js +1 -1
  85. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.js +1 -1
  86. package/dist/src/internal/workflow/runtime.d.ts +1 -0
  87. package/dist/src/public/channels/slack/attachments.js +1 -1
  88. package/dist/src/public/channels/slack/auth.d.ts +2 -0
  89. package/dist/src/public/channels/slack/auth.js +1 -1
  90. package/dist/src/public/channels/slack/defaults.js +2 -2
  91. package/dist/src/public/channels/slack/inbound.d.ts +4 -11
  92. package/dist/src/public/channels/slack/inbound.js +1 -2
  93. package/dist/src/public/channels/slack/model-context.d.ts +28 -0
  94. package/dist/src/public/channels/slack/model-context.js +3 -0
  95. package/dist/src/public/channels/slack/slackChannel.d.ts +8 -0
  96. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  97. package/dist/src/public/connections/index.d.ts +1 -1
  98. package/dist/src/public/definitions/agent.d.ts +1 -1
  99. package/dist/src/public/definitions/approval.d.ts +40 -0
  100. package/dist/src/public/definitions/approval.js +1 -0
  101. package/dist/src/public/definitions/connections/mcp.d.ts +11 -9
  102. package/dist/src/public/definitions/connections/mcp.js +1 -1
  103. package/dist/src/public/definitions/connections/openapi.d.ts +9 -7
  104. package/dist/src/public/definitions/connections/openapi.js +1 -1
  105. package/dist/src/public/definitions/tool.d.ts +7 -20
  106. package/dist/src/public/index.d.ts +1 -1
  107. package/dist/src/public/tools/approval/approval-helpers.d.ts +7 -7
  108. package/dist/src/public/tools/approval/approval-helpers.js +1 -1
  109. package/dist/src/public/tools/approval/index.d.ts +1 -1
  110. package/dist/src/public/tools/index.d.ts +2 -1
  111. package/dist/src/public/tools/internal.js +1 -1
  112. package/dist/src/runtime/agent/bootstrap.d.ts +1 -0
  113. package/dist/src/runtime/agent/bootstrap.js +1 -1
  114. package/dist/src/runtime/agent/mock-model-adapter.js +2 -3
  115. package/dist/src/runtime/attributes/emit.d.ts +2 -43
  116. package/dist/src/runtime/attributes/emit.js +1 -1
  117. package/dist/src/runtime/attributes/normalize.d.ts +17 -0
  118. package/dist/src/runtime/attributes/normalize.js +1 -0
  119. package/dist/src/runtime/connections/mcp-client.d.ts +3 -3
  120. package/dist/src/runtime/connections/mcp-client.js +1 -1
  121. package/dist/src/runtime/connections/registry.d.ts +2 -2
  122. package/dist/src/runtime/connections/resolve-authorization.d.ts +11 -0
  123. package/dist/src/runtime/connections/resolve-authorization.js +1 -0
  124. package/dist/src/runtime/connections/types.d.ts +27 -11
  125. package/dist/src/runtime/framework-tools/connection-search-dynamic.js +1 -1
  126. package/dist/src/runtime/resolve-agent-graph.js +1 -1
  127. package/dist/src/runtime/resolve-agent.js +1 -1
  128. package/dist/src/runtime/resolve-connection.js +1 -1
  129. package/dist/src/runtime/resolve-tool.d.ts +1 -1
  130. package/dist/src/runtime/resolve-tool.js +1 -1
  131. package/dist/src/runtime/sessions/compiled-agent-cache.js +1 -1
  132. package/dist/src/runtime/types.d.ts +8 -7
  133. package/dist/src/setup/primitives/pm/pnpm.js +6 -5
  134. package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
  135. package/dist/src/setup/scaffold/create/project.js +2 -2
  136. package/dist/src/setup/scaffold/update/channels.js +1 -1
  137. package/dist/src/shared/agent-definition.d.ts +11 -13
  138. package/dist/src/shared/dynamic-tool-definition.d.ts +3 -3
  139. package/dist/src/shared/tool-definition.d.ts +1 -2
  140. package/dist/src/shared/workflow-sandbox.d.ts +37 -0
  141. package/dist/src/shared/workflow-sandbox.js +1 -0
  142. package/docs/agent-config.md +30 -10
  143. package/docs/channels/custom.mdx +2 -2
  144. package/docs/channels/slack.mdx +7 -13
  145. package/docs/connections/mcp.mdx +2 -2
  146. package/docs/connections/openapi.mdx +37 -2
  147. package/docs/connections/overview.mdx +32 -0
  148. package/docs/guides/deployment.md +2 -2
  149. package/docs/guides/dynamic-workflows.md +1 -7
  150. package/docs/guides/frontend/overview.mdx +1 -1
  151. package/docs/guides/frontend/use-eve-agent-svelte.mdx +1 -1
  152. package/docs/guides/frontend/use-eve-agent-vue.mdx +1 -1
  153. package/docs/guides/session-context.md +2 -1
  154. package/docs/reference/typescript-api.md +2 -2
  155. package/docs/subagents.mdx +2 -2
  156. package/docs/tools/human-in-the-loop.md +43 -6
  157. package/docs/tools/overview.mdx +3 -3
  158. package/docs/tutorial/first-agent.mdx +1 -1
  159. package/docs/tutorial/guard-the-spend.mdx +4 -3
  160. package/docs/tutorial/ship-it.mdx +1 -1
  161. package/package.json +14 -11
  162. package/dist/src/compiled/@ai-sdk/anthropic/_provider-utils.d.ts +0 -15
  163. package/dist/src/compiled/@ai-sdk/google/_provider-utils.d.ts +0 -11
  164. package/dist/src/compiled/@ai-sdk/openai/_provider-utils.d.ts +0 -15
  165. package/dist/src/compiled/@ai-sdk/provider/_json-schema.d.ts +0 -5
  166. package/dist/src/execution/dispatch-code-mode-runtime-actions-step.d.ts +0 -21
  167. package/dist/src/execution/dispatch-code-mode-runtime-actions-step.js +0 -1
  168. package/dist/src/harness/code-mode-interrupt-state.d.ts +0 -26
  169. package/dist/src/harness/code-mode-interrupt-state.js +0 -1
  170. package/dist/src/harness/code-mode-lifecycle.d.ts +0 -16
  171. package/dist/src/harness/code-mode-lifecycle.js +0 -1
  172. package/dist/src/harness/code-mode-runtime-action-state.d.ts +0 -6
  173. package/dist/src/harness/code-mode-runtime-action-state.js +0 -1
  174. package/dist/src/harness/code-mode.d.ts +0 -26
  175. package/dist/src/harness/code-mode.js +0 -1
  176. package/dist/src/harness/sandbox-surface.d.ts +0 -68
  177. package/dist/src/harness/sandbox-surface.js +0 -1
  178. package/dist/src/internal/nitro/host/code-mode-runtime-dependency-plugin.d.ts +0 -1
  179. package/dist/src/internal/nitro/host/code-mode-runtime-dependency-plugin.js +0 -1
  180. package/dist/src/runtime/framework-tools/code-mode-connection-auth.d.ts +0 -29
  181. package/dist/src/runtime/framework-tools/code-mode-connection-auth.js +0 -1
  182. package/dist/src/shared/code-mode.d.ts +0 -29
  183. package/dist/src/shared/code-mode.js +0 -1
@@ -1,4 +1,4 @@
1
- import type { LanguageModel } from "ai";
1
+ import type { CallSettings, LanguageModel } from "ai";
2
2
  import type { StandardJSONSchemaV1 } from "#compiled/@standard-schema/spec/index.js";
3
3
  import type { JsonObject } from "#shared/json.js";
4
4
  import type { ModuleSourceRef } from "#shared/source-ref.js";
@@ -9,6 +9,10 @@ import type { ModuleSourceRef } from "#shared/source-ref.js";
9
9
  export interface AgentModelOptionsDefinition {
10
10
  readonly providerOptions?: Record<string, JsonObject>;
11
11
  }
12
+ /**
13
+ * Provider-agnostic reasoning effort forwarded to the AI SDK model call.
14
+ */
15
+ export type AgentReasoningDefinition = NonNullable<CallSettings["reasoning"]>;
12
16
  /**
13
17
  * How an agent's model is reached at runtime, decided at compile time from the
14
18
  * authored model value.
@@ -93,20 +97,8 @@ export interface PublicAgentCompactionDefinition {
93
97
  * Experimental, opt-in agent capabilities authored in `agent.ts`.
94
98
  *
95
99
  * These options are unstable and may change or be removed in any release.
96
- * Each agent (the root agent and every subagent) carries its own flags, so
97
- * code mode can be enabled for the whole graph, only a subagent, or only
98
- * the parent.
99
100
  */
100
101
  export interface AgentExperimentalDefinition {
101
- /**
102
- * Routes executable tools through a sandboxed code-execution wrapper
103
- * instead of exposing them directly to the model. The model writes
104
- * JavaScript that calls the tools inside the sandbox.
105
- *
106
- * When unset, eve falls back to the `EVE_EXPERIMENTAL_CODE_MODE`
107
- * environment variable (`"1"` enables it) for backwards compatibility.
108
- */
109
- readonly codeMode?: boolean;
110
102
  /**
111
103
  * Durable Workflow runtime configuration. Root agents may use this to select
112
104
  * the Workflow world backing sessions and runs.
@@ -161,6 +153,7 @@ export type InternalAgentDefinition = {
161
153
  experimental?: AgentExperimentalDefinition;
162
154
  model: InternalAgentModelDefinition;
163
155
  outputSchema?: JsonObject;
156
+ reasoning?: AgentReasoningDefinition;
164
157
  source?: ModuleSourceRef;
165
158
  };
166
159
  /**
@@ -199,6 +192,11 @@ export type PublicAgentDefinition = {
199
192
  */
200
193
  readonly modelContextWindowTokens?: number;
201
194
  readonly modelOptions?: AgentModelOptionsDefinition;
195
+ /**
196
+ * Provider-agnostic reasoning effort for the agent's turn model calls.
197
+ * Support for individual levels depends on the selected model and provider.
198
+ */
199
+ readonly reasoning?: AgentReasoningDefinition;
202
200
  /**
203
201
  * Optional structured return type used when this agent runs in task mode
204
202
  * (for example as a subagent, schedule, or remote job). Interactive
@@ -1,7 +1,7 @@
1
1
  import type { ModelMessage } from "ai";
2
2
  import type { PublicToolInputSchema, PublicToolOutputSchema, ToolModelOutput } from "#shared/tool-definition.js";
3
3
  import type { SessionContext } from "#public/definitions/callback-context.js";
4
- import type { NeedsApprovalContext } from "#public/definitions/tool.js";
4
+ import type { Approval } from "#public/definitions/approval.js";
5
5
  import type { SessionAuth } from "#context/keys.js";
6
6
  import type { HandleMessageStreamEvent } from "#protocol/message.js";
7
7
  type ToolContext = SessionContext;
@@ -64,13 +64,13 @@ export interface DynamicToolEntry<TInput = Record<string, unknown>, TOutput = an
64
64
  readonly toModelOutput?: (output: TOutput) => ToolModelOutput | Promise<ToolModelOutput>;
65
65
  /**
66
66
  * Optional per-call approval gate, mirroring the authored-tool
67
- * `needsApproval` contract: return `true` to require user approval
67
+ * `approval` contract: return `"user-approval"` to require user approval
68
68
  * before the call executes. Only honored for step-scoped dynamic
69
69
  * tools, whose live `execute` closures survive into the harness;
70
70
  * session/turn-scoped tools replay from durable metadata and cannot
71
71
  * carry a function across replay.
72
72
  */
73
- readonly needsApproval?: (ctx: NeedsApprovalContext) => boolean;
73
+ readonly approval?: Approval;
74
74
  }
75
75
  /**
76
76
  * A resolved tool set: keys are entry identifiers, values are
@@ -32,8 +32,7 @@ export interface PublicToolDefinition<TInput = unknown, TOutput = unknown> exten
32
32
  inputSchema: PublicToolInputSchema<TInput>;
33
33
  /**
34
34
  * Optional schema describing the value returned by the tool executor.
35
- * Code mode uses this to expose typed host-tool return values to the
36
- * generated program, and the AI SDK can use it for tool result typing.
35
+ * The AI SDK can use this for tool result typing.
37
36
  */
38
37
  outputSchema?: PublicToolOutputSchema<TOutput>;
39
38
  }
@@ -0,0 +1,37 @@
1
+ import type { ToolSet } from "ai";
2
+ import type * as CodeModeModule from "#compiled/experimental-ai-sdk-code-mode/index.js";
3
+ /** Model-facing tool name for eve's dynamic subagent orchestration tool. */
4
+ export declare const WORKFLOW_TOOL_NAME = "Workflow";
5
+ type WorkflowSandboxModule = Pick<typeof CodeModeModule, "continueCodeModeInterrupt" | "createCodeModeTool" | "getCodeModeInterrupt" | "requestCodeModeInterrupt" | "unwrapCodeModeResult">;
6
+ export type WorkflowSandboxInterrupt = CodeModeModule.CodeModeInterrupt;
7
+ export type WorkflowSandboxLifecycle = NonNullable<CodeModeModule.CodeModeOptions["lifecycle"]>;
8
+ export type WorkflowSandboxContinuationSecurity = CodeModeModule.CodeModeContinuationSecurityOptions;
9
+ export declare function installWorkflowSandboxModule(module: WorkflowSandboxModule): void;
10
+ export declare function createWorkflowSandboxTool(input: {
11
+ readonly continuationSecurity: WorkflowSandboxContinuationSecurity;
12
+ readonly hostTools: ToolSet;
13
+ readonly lifecycle?: WorkflowSandboxLifecycle;
14
+ }): Promise<ToolSet[string]>;
15
+ export declare function requestWorkflowSandboxInterrupt(input: {
16
+ readonly kind: string;
17
+ readonly runtimeAction: unknown;
18
+ readonly toolInput: unknown;
19
+ readonly toolName: string;
20
+ }): Promise<unknown>;
21
+ export declare function getWorkflowSandboxInterrupt(result: unknown, continuationSecurity: WorkflowSandboxContinuationSecurity): Promise<WorkflowSandboxInterrupt | undefined>;
22
+ export declare function continueWorkflowSandboxInterrupt(input: {
23
+ readonly continuationSecurity: WorkflowSandboxContinuationSecurity;
24
+ readonly interrupt: WorkflowSandboxInterrupt;
25
+ readonly lifecycle?: WorkflowSandboxLifecycle;
26
+ readonly resolution: unknown;
27
+ readonly tools: ToolSet;
28
+ }): Promise<unknown>;
29
+ export declare function unwrapWorkflowSandboxResult(value: unknown, continuationSecurity: WorkflowSandboxContinuationSecurity): Promise<{
30
+ readonly output: unknown;
31
+ readonly status: "completed";
32
+ } | {
33
+ readonly interrupt: WorkflowSandboxInterrupt;
34
+ readonly status: "interrupted";
35
+ }>;
36
+ export declare function readWorkflowSandboxResolution(options: unknown): unknown;
37
+ export {};
@@ -0,0 +1 @@
1
+ const WORKFLOW_TOOL_NAME=`Workflow`,WORKFLOW_SANDBOX_MODULE_KEY=Symbol.for(`eve.workflowSandbox.module`),WORKFLOW_SANDBOX_MODULE_SPECIFIER=[`#compiled`,`experimental-ai-sdk-code-mode`,`index.js`].join(`/`);let workflowSandboxModulePromise;function installWorkflowSandboxModule(e){globalThis[WORKFLOW_SANDBOX_MODULE_KEY]=e}async function createWorkflowSandboxTool(e){let{createCodeModeTool:t}=await loadWorkflowSandboxModule();return t(e.hostTools,createWorkflowSandboxOptions(e.continuationSecurity,e.lifecycle))}async function requestWorkflowSandboxInterrupt(e){let{requestCodeModeInterrupt:t}=await loadWorkflowSandboxModule();return t(e)}async function getWorkflowSandboxInterrupt(e,t){let{getCodeModeInterrupt:n}=await loadWorkflowSandboxModule();return n(e,t)}async function continueWorkflowSandboxInterrupt(e){let{continueCodeModeInterrupt:t}=await loadWorkflowSandboxModule();return t({interrupt:e.interrupt,options:createWorkflowSandboxOptions(e.continuationSecurity,e.lifecycle),resolution:e.resolution,tools:e.tools})}async function unwrapWorkflowSandboxResult(e,t){let{unwrapCodeModeResult:n}=await loadWorkflowSandboxModule();return n(e,t)}function readWorkflowSandboxResolution(e){if(typeof e!=`object`||!e)return;let t=e.codeModeInterrupt;if(!(typeof t!=`object`||!t))return t.resolution}function createWorkflowSandboxOptions(e,t){let n={continuationSecurity:e};return t!==void 0&&(n.lifecycle=t),n}async function loadWorkflowSandboxModule(){let e=globalThis[WORKFLOW_SANDBOX_MODULE_KEY];return e===void 0?(workflowSandboxModulePromise??=importWorkflowSandboxModule(WORKFLOW_SANDBOX_MODULE_SPECIFIER),await workflowSandboxModulePromise):e}async function importWorkflowSandboxModule(e){return await import(e)}export{WORKFLOW_TOOL_NAME,continueWorkflowSandboxInterrupt,createWorkflowSandboxTool,getWorkflowSandboxInterrupt,installWorkflowSandboxModule,readWorkflowSandboxResolution,requestWorkflowSandboxInterrupt,unwrapWorkflowSandboxResult};
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: "agent.ts"
3
- description: "Set the agent's runtime config in agent.ts with defineAgent, including the model and compaction."
3
+ description: "Set the agent's runtime config in agent.ts with defineAgent, including the model, reasoning effort, and compaction."
4
4
  ---
5
5
 
6
6
  An agent's `agent.ts` calls `defineAgent` (from `eve`) to set its runtime config.
@@ -33,12 +33,33 @@ import { anthropic } from "@ai-sdk/anthropic";
33
33
  import { defineAgent } from "eve";
34
34
 
35
35
  export default defineAgent({
36
- model: anthropic("claude-opus-4.8"),
36
+ model: anthropic("claude-opus-4-8"),
37
37
  });
38
38
  ```
39
39
 
40
+ Direct provider model ids use the provider's native format. For Anthropic, the
41
+ version uses hyphens (`claude-opus-4-8`), while the Gateway id above uses a dot
42
+ (`anthropic/claude-opus-4.8`).
43
+
40
44
  Model use is subject to the terms, data-processing commitments, retention behavior, and available controls of the selected provider and routing path. Review the [AI Gateway model catalog](https://vercel.com/ai-gateway/models) for gateway-routed models, and review the provider's terms when you configure a direct `LanguageModel`.
41
45
 
46
+ ## Reasoning effort
47
+
48
+ Set `reasoning` to control the model's reasoning effort through AI SDK's
49
+ provider-agnostic option:
50
+
51
+ ```ts title="agent/agent.ts"
52
+ export default defineAgent({
53
+ model: "openai/gpt-5.5",
54
+ reasoning: "high",
55
+ });
56
+ ```
57
+
58
+ Supported values are `"provider-default"`, `"none"`, `"minimal"`, `"low"`,
59
+ `"medium"`, `"high"`, and `"xhigh"`. The selected model and provider determine
60
+ which levels are available and how they map to provider-native settings. Use
61
+ `modelOptions.providerOptions` when you need provider-specific reasoning controls.
62
+
42
63
  ## Compaction
43
64
 
44
65
  Compaction summarizes older turns as you approach the context window. It's on by default, so you only tune when it kicks in. Lower `thresholdPercent` to compact sooner:
@@ -85,14 +106,13 @@ external in hosted output, list it in `build.externalDependencies`.
85
106
 
86
107
  `defineAgent` takes a few more fields, all optional. For the exported types, see the [TypeScript API](./reference/typescript-api).
87
108
 
88
- | Field | Type | Default | Description |
89
- | -------------- | ------------------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
90
- | `modelOptions` | `AgentModelOptionsDefinition` | none | Provider option overrides forwarded to the model call. |
91
- | `experimental` | `{ codeMode?: boolean; workflow?: { world?: string } }` | flags unset | Opt-in flags that can change or disappear in any release. Treat them as unstable. `codeMode` routes executable tools through a sandboxed code-execution wrapper, where the model writes JavaScript that calls the tools inside the [sandbox](./sandbox). `workflow.world` selects the Workflow world package backing session state, queues, hooks, and streams on the root agent. |
92
- | `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. |
93
- | `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. |
94
-
95
- `codeMode` is experimental and may change or be removed.
109
+ | Field | Type | Default | Description |
110
+ | -------------- | --------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
111
+ | `reasoning` | `AgentReasoningDefinition` | provider default | Provider-agnostic reasoning effort forwarded to the agent's turn model calls. |
112
+ | `modelOptions` | `AgentModelOptionsDefinition` | none | Provider option overrides forwarded to the model call. |
113
+ | `experimental` | `{ workflow?: { world?: string } }` | unset | Opt-in settings that can change or disappear in any release. Treat them as unstable. `workflow.world` selects the Workflow world package backing session state, queues, hooks, and streams on the root agent. |
114
+ | `outputSchema` | Standard Schema or a JSON Schema object | none | Structured return type for task-mode runs (a subagent, schedule, or remote job). Interactive conversation turns ignore it unless the client supplies a per-message schema. |
115
+ | `build` | `{ externalDependencies?: string[] }` | none | Hosted-build packaging controls. `externalDependencies` keeps listed packages external while eve compiles authored modules such as tools and channels, and traces those packages into the hosted output. |
96
116
 
97
117
  `externalDependencies` is a packaging control only. It keeps selected packages as runtime dependencies in the hosted output; it does not authorize, configure, or review any third-party service those packages may call.
98
118
 
@@ -46,7 +46,7 @@ export default defineChannel({
46
46
 
47
47
  Declare routes with the `POST()` and `GET()` helpers. Each route handler receives the raw `Request` and a helpers object:
48
48
 
49
- - `send(message, { auth, continuationToken, state? })` starts or resumes a session. Returns a `Session`.
49
+ - `send(message, { auth, continuationToken, state?, title? })` starts or resumes a session. `title` overrides the new workflow session's display title without changing the model message. Returns a `Session`.
50
50
  - `getSession(sessionId)` looks up an existing session. The returned `Session` exposes `getEventStream({ startIndex? })` for streaming.
51
51
  - `receive(channel, ...)` hands inbound work to a different channel for cross-channel hand-off.
52
52
  - `params` holds route parameters extracted from the path pattern.
@@ -182,7 +182,7 @@ When a parent agent dispatches a subagent, the framework forwards the parent's c
182
182
 
183
183
  ## Continuation tokens
184
184
 
185
- Each call to `send(message, { auth, continuationToken, state? })` from a channel route addresses a session by its channel-local raw token. The framework prepends the channel name, derived from the file stem under `agent/channels/`, before handing the token to the runtime.
185
+ Each call to `send(message, { auth, continuationToken, state?, title? })` from a channel route addresses a session by its channel-local raw token. The framework prepends the channel name, derived from the file stem under `agent/channels/`, before handing the token to the runtime.
186
186
 
187
187
  ```ts
188
188
  import { slackContinuationToken } from "eve/channels/slack";
@@ -54,28 +54,22 @@ Inbound hooks decide whether to dispatch a turn and with what `auth`. Return `{
54
54
  - `onDirectMessage(ctx, message)` handles `message.im` events (needs `im:history` scope). Bot-authored messages and edits are filtered out first.
55
55
  - `onInteraction(action, ctx)` handles `block_actions` callbacks not consumed by HITL.
56
56
 
57
- You get the triggering mention by default, but not the earlier replies in the thread. Pull them in with `loadThreadContextMessages` and return them as `context`, which eve appends to history as user messages the model sees on every later turn. Use `since: "last-agent-reply"` so repeated mentions in one thread inject only what is new:
57
+ eve attaches the triggering Slack user id to the same model message as the message text. This keeps speaker attribution intact when several people use one thread without making profile lookup requests.
58
+
59
+ You get the triggering mention by default, but not the earlier replies in the thread. Enable `threadContext` to fetch and inject them with every message attributed by stable Slack user id. Use `since: "last-agent-reply"` so repeated mentions inject only what is new:
58
60
 
59
61
  ```ts
60
- import { defaultSlackAuth, loadThreadContextMessages, slackChannel } from "eve/channels/slack";
62
+ import { slackChannel } from "eve/channels/slack";
61
63
  import { connectSlackCredentials } from "@vercel/connect/eve";
62
64
 
63
65
  export default slackChannel({
64
66
  credentials: connectSlackCredentials("slack/my-agent"),
65
- async onAppMention(ctx, message) {
66
- const auth = defaultSlackAuth(message, ctx);
67
- const prior = await loadThreadContextMessages(ctx.thread, message, {
68
- since: "last-agent-reply",
69
- });
70
- if (prior.length === 0) return { auth };
71
- const transcript = prior
72
- .map((m) => `${m.isMe ? "you" : (m.user ?? "user")}: ${m.markdown}`)
73
- .join("\n");
74
- return { auth, context: [`Recent thread messages since your last reply:\n\n${transcript}`] };
75
- },
67
+ threadContext: { since: "last-agent-reply" },
76
68
  });
77
69
  ```
78
70
 
71
+ `threadContext` performs one `conversations.replies` request for each triggering thread reply and requires the matching Slack history scope. Omit it when the agent should see only direct mentions. `loadThreadContextMessages` remains available when you need custom filtering or non-model processing of the raw thread messages.
72
+
79
73
  ### Delivery
80
74
 
81
75
  The default handlers reply in-thread and show progress. Typing indicators post automatically: `Thinking…` on inbound, `Working…` on `turn.started`, a truncated reasoning snippet on `reasoning.appended`, and tool status on `actions.requested`. Reasoning snippets build progressively: extensions of at least four characters appear immediately, while smaller streamed deltas use the five-second refresh interval to avoid one Slack request per token. Override `events["reasoning.appended"]` if you prefer generic wording. Override `onAppMention` or the `events` handlers to customize.
@@ -48,8 +48,8 @@ Use `allow` for the smallest safe surface, especially on MCP servers that expose
48
48
 
49
49
  MCP connections support the shared connection options:
50
50
 
51
- - `auth` for static tokens, Vercel Connect, or self-hosted interactive OAuth.
52
- - `headers` for API-key schemes or extra server configuration.
51
+ - `auth` for static tokens, Vercel Connect, self-hosted interactive OAuth, or a per-caller provider resolver.
52
+ - `headers` for static or per-caller API-key schemes and extra server configuration.
53
53
  - `approval` for human-in-the-loop gates before connection tools run.
54
54
 
55
55
  See [Connections](/docs/connections) for the shared auth, headers, and approval shapes.
@@ -34,6 +34,41 @@ OpenAPI connections use the shared connection fields from [Connections](/docs/co
34
34
 
35
35
  Use `baseUrl` when the spec's `servers` list is absent, points at the wrong environment, or needs to be pinned for this agent.
36
36
 
37
+ ## Path parameters
38
+
39
+ When an operation path contains dynamic segments, declare each segment as an OpenAPI path parameter. eve exposes path, query, header, and cookie parameters as top-level tool inputs, then substitutes `in: "path"` values into the matching `{name}` placeholder before making the request.
40
+
41
+ ```ts title="agent/connections/cart.ts"
42
+ import { defineOpenAPIConnection } from "eve/connections";
43
+
44
+ export default defineOpenAPIConnection({
45
+ baseUrl: "https://api.example.com",
46
+ description: "Cart and checkout API.",
47
+ spec: {
48
+ openapi: "3.0.3",
49
+ info: { title: "Cart API", version: "1.0.0" },
50
+ paths: {
51
+ "/api/{dynamicsegment}/somethingelse": {
52
+ get: {
53
+ operationId: "getSomethingElse",
54
+ parameters: [
55
+ {
56
+ name: "dynamicsegment",
57
+ in: "path",
58
+ required: true,
59
+ schema: { type: "string" },
60
+ },
61
+ ],
62
+ responses: { "200": { description: "OK" } },
63
+ },
64
+ },
65
+ },
66
+ },
67
+ });
68
+ ```
69
+
70
+ The parameter `name` must exactly match the placeholder inside the path. If the spec omits the `in: "path"` parameter, the generated tool has no input for that segment and eve cannot fill it in from query parameters.
71
+
37
72
  ## Operation filters
38
73
 
39
74
  To narrow which generated tools the model sees, set exactly one of `operations.allow` or `operations.block`:
@@ -55,8 +90,8 @@ Filters match `operationId`. If an operation does not declare one, use the deter
55
90
 
56
91
  OpenAPI connections support the shared connection options:
57
92
 
58
- - `auth` for static tokens, Vercel Connect, or self-hosted interactive OAuth.
59
- - `headers` for API-key schemes or extra server configuration.
93
+ - `auth` for static tokens, Vercel Connect, self-hosted interactive OAuth, or a per-caller provider resolver.
94
+ - `headers` for static or per-caller API-key schemes and extra server configuration.
60
95
  - `approval` for human-in-the-loop gates before generated operation tools run.
61
96
 
62
97
  See [Connections](/docs/connections) for the shared auth, headers, and approval shapes.
@@ -57,6 +57,38 @@ export default defineMcpClientConnection({
57
57
  });
58
58
  ```
59
59
 
60
+ ## Per-caller auth and headers
61
+
62
+ When credentials or routing depend on the caller, make `auth` or `headers` a function. eve calls it inside the active turn and passes the same session context exposed to tools and hooks:
63
+
64
+ ```ts title="agent/connections/warehouse.ts"
65
+ import { defineOpenAPIConnection } from "eve/connections";
66
+
67
+ export default defineOpenAPIConnection({
68
+ spec: "https://warehouse.example.com/openapi.json",
69
+ description: "The caller's tenant-scoped warehouse.",
70
+ auth: (ctx) => ({
71
+ principalType: "user",
72
+ getToken: async () => ({
73
+ token: await tenantToken(ctx.session.auth.current),
74
+ }),
75
+ }),
76
+ headers: (ctx) => ({
77
+ "X-Tenant-Id": tenantId(ctx.session.auth.current),
78
+ }),
79
+ });
80
+ ```
81
+
82
+ An `auth` resolver returns the same provider object accepted by static `auth`, including a `connect(...)` provider for interactive OAuth. The resolver itself can be async. Header callbacks can return the whole map, as above, or resolve individual values:
83
+
84
+ ```ts
85
+ headers: {
86
+ "X-Tenant-Id": (ctx) => tenantId(ctx.session.auth.current),
87
+ }
88
+ ```
89
+
90
+ Use `principalType: "user"` for per-user tokens so eve rejects unauthenticated callers and keys its step-local token cache by user. The resolver supplements route auth; it does not authenticate the inbound request. Static auth objects and header maps remain available when every caller shares the same configuration.
91
+
60
92
  ## Per-connection approval
61
93
 
62
94
  To put every tool a connection serves behind a human, use the helpers from `eve/tools/approval`:
@@ -74,11 +74,11 @@ import { anthropic } from "@ai-sdk/anthropic";
74
74
  import { defineAgent } from "eve";
75
75
 
76
76
  export default defineAgent({
77
- model: anthropic("claude-opus-4.8"),
77
+ model: anthropic("claude-opus-4-8"),
78
78
  });
79
79
  ```
80
80
 
81
- With that shape, the model call goes directly to Anthropic and the runtime reads `ANTHROPIC_API_KEY`. The same pattern works for OpenAI after installing `@ai-sdk/openai`, using `openai("...")`, and setting `OPENAI_API_KEY`. This is the usual choice when self-deploying without any Vercel-managed services.
81
+ With that shape, the model call goes directly to Anthropic and the runtime reads `ANTHROPIC_API_KEY`. Direct Anthropic model ids use hyphens (`claude-opus-4-8`), unlike the dotted Gateway id (`anthropic/claude-opus-4.8`). The same pattern works for OpenAI after installing `@ai-sdk/openai`, using `openai("...")`, and setting `OPENAI_API_KEY`. This is the usual choice when self-deploying without any Vercel-managed services.
82
82
 
83
83
  ## 4. Sandbox backend
84
84
 
@@ -3,7 +3,7 @@ title: "Dynamic Workflows"
3
3
  description: "The experimental Workflow tool: let the model orchestrate its own subagents from model-authored JavaScript as one durable step."
4
4
  ---
5
5
 
6
- The experimental `Workflow` tool lets the model write JavaScript that coordinates the agent's own subagents as a single durable step. The program can run them in sequence, feed one result into the next, fan out over a list, and combine the results. You enable the capability and the model decides and runs the orchestration. It is the agents-only slice of [code mode](../agent-config#other-defineagent-fields) (the broader `codeMode` flag that routes all of an agent's tools through model-authored JavaScript).
6
+ The experimental `Workflow` tool lets the model write JavaScript that coordinates the agent's own subagents as a single durable step. The program can run them in sequence, feed one result into the next, fan out over a list, and combine the results. You enable the capability and the model decides and runs the orchestration.
7
7
 
8
8
  A single turn can already call several subagents, and parallel tool calls dispatch concurrently. What a workflow adds is _programmatic_ coordination. The program decides how many subagents to run based on an earlier result, which output feeds which call, and how to combine everything. That is logic the model cannot express as a few one-off calls.
9
9
 
@@ -63,12 +63,6 @@ That is an allowlist, not a denylist. The sandbox cannot read files, open a sock
63
63
  - **Approval-safe.** A subagent that needs human approval (HITL, human-in-the-loop) mid-run surfaces its request to the user, and the workflow picks back up once that is answered, same as direct delegation.
64
64
  - **Observable.** Every orchestrated subagent emits the usual `subagent.called` / `subagent.completed` events on the parent stream and gets its own child session and stream. The telemetry matches direct delegation, so existing dashboards and cost attribution keep working.
65
65
 
66
- ## Relationship to code mode
67
-
68
- [Code mode](../agent-config#other-defineagent-fields) is the broader version, where the model drives _all_ of an agent's tools (files, shell, web, and agents) from JavaScript. A workflow covers only the subagents. The two do not interfere. Enabling the `Workflow` tool leaves code mode untouched, and an agent can run both at once.
69
-
70
- `codeMode` is experimental and may change or be removed.
71
-
72
66
  ## What to read next
73
67
 
74
68
  - Declare the subagents a workflow orchestrates → [Subagents](../subagents)
@@ -100,7 +100,7 @@ Assistant text, reasoning, tool calls, and tool results stream into `data` as th
100
100
 
101
101
  ## Human-in-the-loop prompts
102
102
 
103
- Tools opt into approval with `needsApproval`, 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()`:
103
+ Tools opt into approval with `approval`, and the model can also ask a question with `ask_question` — see [Human-in-the-loop](/docs/human-in-the-loop) for the server-side model. Either way the stream emits an `input.requested` event, and the pending request rides on a `dynamic-tool` part of the latest message at `part.toolMetadata?.eve?.inputRequest`. Read it, then answer through the same session with `send()`:
104
104
 
105
105
  ```tsx
106
106
  const request = agent.data.messages
@@ -78,7 +78,7 @@ await agent.send({
78
78
 
79
79
  ## Human-in-the-loop prompts
80
80
 
81
- A tool opts into approval with `needsApproval` ([Tools](../../tools)). When one fires, the pending request rides along on a `dynamic-tool` part of the latest message at `part.toolMetadata?.eve?.inputRequest`. Read it, then answer through the same session with `agent.send({ inputResponses })`:
81
+ A tool opts into approval with `approval` ([Tools](../../tools)). When one fires, the pending request rides along on a `dynamic-tool` part of the latest message at `part.toolMetadata?.eve?.inputRequest`. Read it, then answer through the same session with `agent.send({ inputResponses })`:
82
82
 
83
83
  ```ts
84
84
  import type { EveDynamicToolPart, EveMessagePart } from "eve/svelte";
@@ -89,7 +89,7 @@ async function onFileChange(event: Event) {
89
89
 
90
90
  ## Human-in-the-loop prompts
91
91
 
92
- A tool opts into approval with `needsApproval` ([Tools](../../tools)). When it triggers, the pending request shows up as a `dynamic-tool` part on the latest message at `part.toolMetadata?.eve?.inputRequest`. Read it, then answer through the same session with `send({ inputResponses })`:
92
+ A tool opts into approval with `approval` ([Tools](../../tools)). When it triggers, the pending request shows up as a `dynamic-tool` part on the latest message at `part.toolMetadata?.eve?.inputRequest`. Read it, then answer through the same session with `send({ inputResponses })`:
93
93
 
94
94
  ```ts
95
95
  import type { EveDynamicToolPart, EveMessagePart } from "eve/vue";
@@ -3,7 +3,7 @@ title: "Session Context"
3
3
  description: "Runtime helpers: ctx.session, ctx.getSandbox, ctx.getSkill, and defineState."
4
4
  ---
5
5
 
6
- eve exposes runtime state through the `ctx` parameter passed to tool `execute`, hook handlers, and channel event handlers:
6
+ eve exposes runtime state through the `ctx` parameter passed to tool `execute`, hook handlers, channel event handlers, and connection auth/header resolvers:
7
7
 
8
8
  - `ctx.session`: session metadata, turn, auth, and parent lineage
9
9
  - `ctx.getSandbox()`: live sandbox handle for the current agent
@@ -119,6 +119,7 @@ export const budget = defineState<BudgetState>("myapp.budget", () => ({
119
119
  Safe places:
120
120
 
121
121
  - inside `defineTool(...).execute(input, ctx)`
122
+ - inside connection `auth: (ctx) => provider` and `headers: (ctx) => values` resolvers
122
123
  - inside authored callbacks eve runs inside the runtime
123
124
  - after asynchronous boundaries inside the same authored execution chain
124
125
 
@@ -51,11 +51,11 @@ export default defineTool({
51
51
  | `defineEvalConfig` | `eve/evals` | `evals/evals.config.ts` | [Evals](../evals/overview) |
52
52
  | `useEveAgent` | `eve/react`, `eve/vue`, `eve/svelte` | frontend | [Frontend](../guides/frontend/overview) |
53
53
 
54
- A few non-`define*` helpers round out the set: `disableTool` and `ExperimentalWorkflow` from `eve/tools` (see [Default harness](../concepts/default-harness)), the route verbs `GET`/`POST`/`PUT`/`PATCH`/`DELETE`/`WS` from `eve/channels`, the approval predicates `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`). `AgentWorkflowDefinition` and `AgentWorkflowWorldDefinition` are exported from `eve` for the `defineAgent({ experimental: { workflow } })` config shape.
54
+ A few non-`define*` helpers round out the set: `disableTool` and `ExperimentalWorkflow` from `eve/tools` (see [Default harness](../concepts/default-harness)), the route verbs `GET`/`POST`/`PUT`/`PATCH`/`DELETE`/`WS` from `eve/channels`, the approval policies `always`/`once`/`never` from `eve/tools/approval`, and the channel auth helpers `localDev`/`vercelOidc`/`placeholderAuth` from `eve/channels/auth`. To wrap a built-in tool, import its default value from `eve/tools/defaults` (`bash`, `readFile`, `writeFile`, `glob`, `grep`, `webFetch`, `webSearch`, `todo`, `loadSkill`). `AgentReasoningDefinition` is exported from `eve` for the top-level `defineAgent({ reasoning })` setting. `AgentWorkflowDefinition` and `AgentWorkflowWorldDefinition` are exported from `eve` for the `defineAgent({ experimental: { workflow } })` config shape.
55
55
 
56
56
  ## Runtime context (`ctx`)
57
57
 
58
- `ctx` is passed to your tool `execute`, hook handlers, and channel event handlers. It is live only while authored code is running, so reaching for it at module top level throws. See [Session context](../guides/session-context) for the full model.
58
+ `ctx` is passed to your tool `execute`, hook handlers, channel event handlers, and connection auth/header resolvers. It is live only while authored code is running, so reaching for it at module top level throws. See [Session context](../guides/session-context) for the full model.
59
59
 
60
60
  | Member | Use |
61
61
  | --------------------------- | ---------------------------------------------------------------------------- |
@@ -16,7 +16,7 @@ Every agent gets an `agent` tool by default. The model calls it to delegate a su
16
16
  }
17
17
  ```
18
18
 
19
- The copy shares the parent's sandbox and tools, and a child's file writes are immediately visible to the parent. That is what makes parallel calls natural: fan out a few copies to fix different files at once. The copy inherits auth and connections, but starts with fresh conversation history and fresh state. If a declared subagent calls `agent`, the child is a copy of _that_ subagent, not the root.
19
+ The copy shares the parent's sandbox and tools, and a child's file writes are immediately visible to the parent. That is what makes parallel calls natural: emit multiple `agent` calls in one response to fan out a small, fixed set of independent subtasks. eve runs that batch concurrently and returns every result before the parent continues. Give children non-overlapping write scopes when they work in the shared sandbox. The copy inherits auth and connections, but starts with fresh conversation history and fresh state. If a declared subagent calls `agent`, the child is a copy of _that_ subagent, not the root.
20
20
 
21
21
  The parent transfers data to the child through the `message` input it gives the subagent. Do not include sensitive data in a subagent request unless that child and its inherited tools, connections, sandbox, and telemetry path are appropriate for that data.
22
22
 
@@ -88,7 +88,7 @@ A declared subagent's tool name is the bare path-derived name, with no prefix. `
88
88
 
89
89
  Because the name lives in the same runtime tool namespace as authored tools, a subagent named `researcher` collides with a tool named `researcher`. eve rejects the build rather than picking a winner, so keep subagent directory names distinct from tool names.
90
90
 
91
- Do not rely on subagent delegation by itself as an approval boundary. Put sensitive tools behind `needsApproval`, connection approval, route/session authorization, or other controls wherever those tools can be called.
91
+ Do not rely on subagent delegation by itself as an approval boundary. Put sensitive tools behind `approval`, connection approval, route/session authorization, or other controls wherever those tools can be called.
92
92
 
93
93
  Each delegated subagent spins up its own child session and stream. The parent stream carries only the control-plane events `subagent.called` and `subagent.completed`. To follow the child's full progress, read `subagent.called.data.childSessionId` and subscribe at `GET /eve/v1/session/:childSessionId/stream`.
94
94
 
@@ -13,7 +13,7 @@ Either way the run parks at `session.waiting`, durably, for as long as it takes
13
13
 
14
14
  ## Approvals
15
15
 
16
- Approval is a property of a [tool](/docs/tools) that pauses for a person before it runs. Gate a tool with `needsApproval` and the helpers from `eve/tools/approval`:
16
+ Approval is a property of a [tool](/docs/tools) that pauses for a person before it runs. Gate a tool with `approval` and the helpers from `eve/tools/approval`:
17
17
 
18
18
  ```ts title="agent/tools/refund_charge.ts"
19
19
  import { defineTool } from "eve/tools";
@@ -22,8 +22,8 @@ import { z } from "zod";
22
22
 
23
23
  export default defineTool({
24
24
  description: "Refund a charge.",
25
- inputSchema: z.object({ chargeId: z.string(), amount: z.number() }),
26
- needsApproval: always(), // or once() / never() / a predicate
25
+ inputSchema: z.object({ tenantId: z.string(), chargeId: z.string(), amount: z.number() }),
26
+ approval: always(), // or once() / never() / a policy
27
27
  async execute(input) {
28
28
  return refund(input);
29
29
  },
@@ -36,16 +36,53 @@ export default defineTool({
36
36
  | `once()` | Require approval only the first time the tool runs in a session; auto-allow after. |
37
37
  | `always()` | Require approval before every call. |
38
38
 
39
- By default, omitted `needsApproval` behaves like `never()`, so tool calls may execute without human approval. Require human approval or other safeguards for sensitive, irreversible, regulated, financial, healthcare, employment, housing, legal, safety-impacting, user-impacting, or external side-effecting actions.
39
+ By default, omitted `approval` behaves like `never()`, so tool calls may execute without human approval. Require human approval or other safeguards for sensitive, irreversible, regulated, financial, healthcare, employment, housing, legal, safety-impacting, user-impacting, or external side-effecting actions.
40
40
 
41
- When the decision depends on the input, pass your own predicate instead of a helper. It receives `{ toolName, toolInput, approvedTools }` and returns a boolean. `toolInput` can be undefined, so guard the access. To require approval only when an amount crosses a threshold:
41
+ When the decision depends on the input, pass your own policy instead of a helper. It receives the same session context as tool execution, plus `{ toolName, toolInput, approvedTools }`, and returns an AI SDK 7 approval status synchronously or as a promise. Use `ctx.session.auth.current` to guard by the caller of the current turn and `ctx.session.auth.initiator` to guard by the caller that created the session. Return `"user-approval"` to pause for a person or `"not-applicable"` to continue without a prompt. `toolInput` can be undefined, so guard the access. This policy denies cross-tenant calls, then requires approval only when an amount crosses a threshold:
42
42
 
43
43
  ```ts
44
- needsApproval: ({ toolInput }) => (toolInput?.amount ?? 0) > 1000,
44
+ approval: ({ session, toolInput }) => {
45
+ const callerTenant = session.auth.current?.attributes.tenantId;
46
+ if (callerTenant === undefined || callerTenant !== toolInput?.tenantId) {
47
+ return { type: "denied", reason: "Caller cannot access this tenant." };
48
+ }
49
+ return (toolInput?.amount ?? 0) > 1000 ? "user-approval" : "not-applicable";
50
+ },
45
51
  ```
46
52
 
53
+ For compatibility with the previous predicate shape, policies may return booleans: `true` is treated as `"user-approval"` and `false` as `"not-applicable"`. Boolean promises are supported too.
54
+
55
+ Policies can also return `"approved"` or `"denied"` to decide automatically. Use `{ type: "approved" | "denied", reason }` when the model should receive a reason. The `Approval`, `ApprovalContext`, and `ApprovalStatus` types are exported from both `eve/tools` and `eve/tools/approval`.
56
+
47
57
  Gating a side effect on approval is also how you make non-idempotent work safe across replays: a charge or email that sits behind `always()` can't fire from a re-run step without a fresh human decision.
48
58
 
59
+ ### Skipping approval for schedule-dispatched turns
60
+
61
+ `session.auth.current` identifies the caller of this turn. Markdown schedules use the app principal (`authenticator: "app"`, `principalId: "eve:app"`, `principalType: "runtime"`) automatically. A `run` schedule must pass its `appAuth` to `receive(...)` for the child session to use that principal. Match all three fields to skip approval for automated turns while still prompting when a person calls the same tool:
62
+
63
+ ```ts title="agent/tools/refund_charge.ts"
64
+ import { defineTool } from "eve/tools";
65
+ import { z } from "zod";
66
+
67
+ export default defineTool({
68
+ description: "Refund a charge.",
69
+ inputSchema: z.object({ chargeId: z.string(), amount: z.number() }),
70
+ approval: ({ session }) => {
71
+ const auth = session.auth.current;
72
+ return auth?.authenticator === "app" &&
73
+ auth.principalId === "eve:app" &&
74
+ auth.principalType === "runtime"
75
+ ? "not-applicable"
76
+ : "user-approval";
77
+ },
78
+ async execute(input) {
79
+ return refund(input);
80
+ },
81
+ });
82
+ ```
83
+
84
+ `session` in `approval` has the same shape as `ctx.session` in `execute`: `id`, `auth`, `turn`, and an optional `parent`. If a person later resumes a schedule-started session, `session.auth.current` becomes that person while `session.auth.initiator` remains the app principal. Inspect `initiator` only when the policy should apply to the whole session. Skipping approval on scheduled turns means any non-idempotent side effect will re-fire if a step replays, so pair this pattern with idempotency keys or `once()` where needed.
85
+
49
86
  ## Questions
50
87
 
51
88
  The built-in `ask_question` tool lets the model pause and ask the user, rather than guessing. It has no `execute` — the model calls it with `{ prompt, options?, allowFreeform? }`:
@@ -46,7 +46,7 @@ eve never runs authored tools during discovery. The model sees descriptors first
46
46
 
47
47
  ## Gate a tool on human approval
48
48
 
49
- A tool can require a person to sign off before it runs. Set `needsApproval` with the helpers from `eve/tools/approval`:
49
+ A tool can require a person to sign off before it runs. Set `approval` with the helpers from `eve/tools/approval`:
50
50
 
51
51
  ```ts title="agent/tools/refund_charge.ts"
52
52
  import { defineTool } from "eve/tools";
@@ -56,14 +56,14 @@ import { z } from "zod";
56
56
  export default defineTool({
57
57
  description: "Refund a charge.",
58
58
  inputSchema: z.object({ chargeId: z.string(), amount: z.number() }),
59
- needsApproval: always(), // or once() / never() / a predicate
59
+ approval: always(), // or once() / never() / a policy
60
60
  async execute(input) {
61
61
  return refund(input);
62
62
  },
63
63
  });
64
64
  ```
65
65
 
66
- Approval is one half of eve's [human-in-the-loop](./human-in-the-loop) model — the page covers the `always/once/never` helpers, input-dependent predicates, and how a gated call pauses and resumes durably.
66
+ Approval is one half of eve's [human-in-the-loop](./human-in-the-loop) model — the page covers the `always/once/never` helpers, input-dependent policies, and how a gated call pauses and resumes durably.
67
67
 
68
68
  ## Shape what the model sees with `toModelOutput`
69
69
 
@@ -10,7 +10,7 @@ Step 1 gets it talking. The scaffold bundles a small sample dataset, so your fir
10
10
  ## Prerequisites
11
11
 
12
12
  - Node 24 or newer and npm.
13
- - A model credential. The scaffold's default model goes through the [Vercel AI Gateway](../getting-started), so you need `AI_GATEWAY_API_KEY` (or `VERCEL_OIDC_TOKEN` pulled via `vercel link`). A direct provider model like `anthropic("claude-opus-4.8")` instead needs that provider's AI SDK package and key, here `@ai-sdk/anthropic` and `ANTHROPIC_API_KEY`.
13
+ - A model credential. The scaffold's default model goes through the [Vercel AI Gateway](../getting-started), so you need `AI_GATEWAY_API_KEY` (or `VERCEL_OIDC_TOKEN` pulled via `vercel link`). A direct provider model like `anthropic("claude-opus-4-8")` instead needs that provider's AI SDK package and key, here `@ai-sdk/anthropic` and `ANTHROPIC_API_KEY`.
14
14
 
15
15
  If you have not run eve before, complete [Getting Started](../getting-started) first. Without a credential, "Run the agent" below fails when the runtime tries to reach the model; the dev TUI's `/model` flow walks you through pasting a key or linking a project.
16
16