# Changelog

New features, breaking changes, and fixes in eve, release by release.

## v0.83.2 {#0.83.2}



### Patch Changes

- A parent agent's message to a subagent no longer answers the subagent's pending tool approval or session-limit prompt. Before, a follow-up such as `approve` or `continue` settled the prompt as if the person had answered it. Now only a person's structured answer settles it: the parent's message is delivered as an ordinary message, so a pending approval resolves as `ignored` and a session-limit prompt keeps waiting for the person. Thanks @devon-seitz for reporting this in #5075.
- When compaction runs partway through a turn, notices the framework sends again, such as the deferred tool catalog notice, now go before the turn's input instead of after the latest tool result, where the model read them as the newest message.
  
  Thanks @hrayn3 for reporting this in #5198.
- The connection sign-in page now says "Authorization not completed" instead of "Authorization complete" when the provider redirects back with an OAuth error, such as the person declining consent. Thanks @dretanacr for reporting this in #5105.
- Connection tool calls now fail after 5 minutes without an answer, instead of holding the turn until it is cancelled. eve cancels the request and returns a tool error the agent can report, so a tool that takes longer than 5 minutes now fails. Thanks @dretanacr for reporting this in #4977.
- Record the input the model sent to an agent tool in eval facts, so a subagent or remote agent call in `turn.toolCalls` no longer shows `input: {}` and `t.calledTool(name, { input })` can match it. Thanks @dretanacr for reporting this in #5063.
- Evals keep an input request pending after a `respond()` that answers only some of the open requests. `session.pendingInputRequests` still lists the unanswered ones, and `parked()` holds (and `succeeded()` fails) while the run waits on them. Thanks @elrumordelaluz for reporting this in #5157.
- An expired session is no longer reported as failed when writing its final `session.completed` event fails. Before, channels such as Slack posted a `session.failed` error after they had already handled `session.completed`. Thanks @bisak for reporting this in #5261.
- A session stream request that does not report the durable tail no longer looks it up. Default opens and client reconnects now check that the session exists with one run lookup, instead of a tail lookup that on the local world opens every chunk file. Unknown and expired sessions still answer 404 and 410 before the stream starts. Thanks @KingAmo for reporting this in #5016.
- MCP connections now fall back to the highest mutually supported legacy protocol version when `server/discover` returns `-32022`. Thanks @zico-io for reporting this in #4406, and @bluepegasus123 for proposing the fallback.
- PDFs that store their pages in compressed object streams, as phone scans and `pdf-lib` output usually do, now get a per-page token estimate instead of one based on file size. A multi-megabyte scan no longer requests compaction on the first step of a session. Thanks @DLME2024 for reporting this and suggesting the fix in #5090.
- `git({ github })` and the deprecated `code({ github })` register their authenticated `gh` tool at session start again, as do dynamic tools built with `defineGhTool` from `eve/extensions/git/sandbox`. Thanks @seahiLin for reporting this in #4986.
- Slack apps that set `onInputResponse` or `approvalChannel` no longer let a message typed in the thread answer an open question. Before, the typed message answered it without running `onInputResponse`, and the answer was the whole `<slack_message>` envelope. The message now reaches the agent as a new message instead.
- On Vercel Sandbox, aborting a `sandbox.run()` or `sandbox.spawn()` command after it starts now kills it, and `run()` rejects instead of waiting, as the `abortSignal` option documents. Before, the command kept running until it exited by itself, including after a turn was cancelled. Thanks @voidhrithik for reporting this in #5301.
- Workflow and step modules can now use `?raw` and other relative asset imports. Before, `eve build` failed with `UNLOADABLE_DEPENDENCY` when a module reachable from a workflow imported a file this way, even though the same import worked in a tool. Thanks @gmstevenson for reporting this in #5269.



## v0.83.1 {#0.83.1}



### Patch Changes

- Dynamic tools now accept an `endsTurn` function, as static tools do. eve replays it from a durable descriptor like `execute`, so a tool returned by a `defineDynamic` resolver can decide from its output whether the call ends the turn.
- Eval artifacts now record client timing for each captured session: when each request was sent and accepted (including time spent retrying `session_not_ready`) and when each event arrived. `eve eval --keep-state` keeps the local eval server's state, including its Workflow data, after the run.
- `eve eval --repeat <n>` and the `repeat` option in `evals.config.ts` run every eval `n` times to measure repeatability. Each attempt is reported as its own result with a 1-based `attempt`, with its own artifact files, Braintrust row, JUnit test case, and Datadog run iteration, and the console summary shows a per-eval pass rate such as `3/5 passed`.
- Model calls no longer resume the session sandbox just to render attachment labels. Images and PDFs that eve staged or already read for the session are served from a bounded in-memory cache, so the sandbox is resumed only when eve needs bytes it doesn't already hold.
- Non-module files under `agent/lib/`, such as a JSON file imported by a helper, no longer fail discovery. eve ignores them like it does in `tools/`, `channels/`, and `hooks/`, and the bundler resolves them when imported.
- Sandbox work no longer delays the model call. Prewarmed sessions start the sandbox in the background, turns resume a sandbox the session already uses as they begin, and dynamic skill files are written in the background; a tool that uses the sandbox waits only for what remains. A first message sent to a prewarmed session no longer waits for prewarming, and its `defineSandbox()` selector runs with the auth of the request that created the session.
- Add correlated OpenTelemetry events for session handover forwarding and inbox unblocking. Receiver observations include a replay-stable Workflow timestamp and are exported by the next existing turn step without adding tracing-only Workflow steps.



## v0.83.0 {#0.83.0}



### Minor Changes

- `DefaultSandbox` now selects its provider once, when eve prepares the sandbox, and records the choice in the build: Vercel Sandbox on Vercel, then Docker when a daemon is reachable, then just-bash only in `eve dev` and `eve eval`. The runtime uses the recorded provider instead of probing the host again, so a build and its server can no longer select different providers. A production `eve build` with neither Vercel nor Docker no longer falls back to just-bash: the build succeeds, and opening the sandbox fails with an error that asks you to start Docker and rebuild, deploy to Vercel, or select a provider explicitly.
  
  `DefaultSandbox.environment().open()` now accepts `networkPolicy`, and its sessions expose `setNetworkPolicy()`. eve forwards the policy to the selected provider. Docker rejects any policy other than `"allow-all"` or `"deny-all"` when it opens the sandbox, instead of starting the container with open network access, and just-bash rejects any policy other than `"allow-all"`.
  
  Sessions now record their sandbox under the provider name `"default"` instead of `vercel`, `docker`, or `just-bash`. Sessions saved by an earlier eve under the provider that `DefaultSandbox` selected resume the same sandbox. When a session's recorded state belongs to another provider or state protocol, for example after you change providers, eve now starts a fresh sandbox instead of failing; the old sandbox is not deleted. This upgrade is one-way: if you roll back to an earlier eve release, sessions created on this release fail to open their sandbox, because earlier releases reject state recorded under `"default"`.
  
  `VercelSandbox.environment()` no longer captures a snapshot when the environment has no `prepare` callback, no managed workspace or skill files, and no `source`. Session sandboxes start from the image and install the base runtime themselves, as `DefaultSandbox` already did on Vercel. Such sessions now apply a `networkPolicy` set on the environment after base setup; before, only a policy passed to `open()` applied, so `VercelSandbox.environment({ networkPolicy })` and `DefaultSandbox.environment({ vercel: { networkPolicy } })` could leave a session with open network access.
- The just-bash sandbox provider now runs on the public `defineSandboxProvider()` API, and `customCommands` and `filesystem` use eve-owned types from `eve/sandbox/just-bash`, such as `JustBashCommand` and `JustBashFilesystem`, that still accept just-bash's `defineCommand()` results and filesystems. Local just-bash templates rebuild once after upgrading, since their keys no longer include custom commands or the filesystem; reading a directory now rejects instead of returning `null`, and a command ending in a `# comment` runs in any working directory.
- Remove the microsandbox sandbox provider. The `eve/sandbox/microsandbox` export and the `microsandbox` option on `DefaultSandbox.environment()` are gone, and `DefaultSandbox` now selects Vercel Sandbox on Vercel, then Docker when a daemon is reachable, then just-bash. To migrate, switch `MicrosandboxSandbox.image()` and `MicrosandboxSandbox.dockerfile()` to `DockerSandbox.image()` and `DockerSandbox.dockerfile()` from `eve/sandbox/docker`, and remove the `microsandbox` dependency. A session that recorded a microsandbox sandbox starts a fresh sandbox from its current provider on its next `ctx.getSandbox()`.
  
  eve no longer cleans up what microsandbox left on your machine. Before you uninstall `microsandbox`, use its tooling to remove sandboxes and snapshots whose names start with `eve-sbx-`. Then delete `.eve/sandbox-cache/microsandbox` in each app. If you used `MicrosandboxSandbox.dockerfile()`, also run `docker rm -f eve-sandbox-registry` to remove the local image registry it started, and remove the local images tagged `127.0.0.1:51921/eve/…`.
  
  Deployed self-modification (`eve/self-modification/remote`) now requires deploying on Vercel. Builds still succeed on any host, but in a deployment outside Vercel the deployed subagent fails with an error that names this requirement when it opens its sandbox.
- **Breaking for custom sandbox providers.** `defineSandboxProvider()` now takes a byte-level `SandboxConnection` (`spawn`, `readFile`, `writeFiles`, `removePath`, `stop`, optional `close` and `extensions`), and eve derives the full sandbox session from it. Built-in providers are unchanged. See the [custom sandbox providers guide](https://eve.dev/docs/sandbox/custom-providers). To migrate a provider:
  
  - Return `{ connection, state }` from `start()` and a connection from `resume()`. `onSandboxStop()` and `onRuntimeShutdown()` become `connection.stop()`, and `onSandboxDelete()` folds into `onSessionEnd()` with `reason: "deleted"`.
  - Replace `ctx.resources` and `ctx.sourceRevision` with `ctx.templateKey()` and `ctx.populate()`, and remove your own `prepare` option, which eve now runs. `environment()` receives `{}` instead of `undefined` when no options are passed. Set `toolSessions: true` to support keyed `invokeTool` calls.
  - Rename `SandboxPreparedArtifact` to `SandboxJson`, `SandboxProviderSessionContext` to `SandboxSessionContext`, and `SandboxProviderPrepareContext` to `SandboxPrepareContext`. `SandboxProviderHandle` and the `SandboxProviderResource*` and `SandboxProviderTargetFile` types are removed, as is `ctx.host`.
  
  `eve/sandbox/provider` also exports `SandboxSessionGoneError`, `SandboxTemplateNotProvisionedError`, and `SANDBOX_AGENT_ENV`. In `eve/sandbox`, `SandboxSession` gains a required `writeFiles()`, so hand-built sessions such as test doubles need one, and `SandboxNetworkPolicy` is now an eve-owned type rather than the Vercel Sandbox SDK's `NetworkPolicy`.
- Sandbox providers now key each sandbox by its session: `start()` must return the existing sandbox for `ctx.session.id` when one exists, and the required `onSessionEnd(ctx, state | null, { reason })` takes no artifact and must delete by key when `state` is `null`. Session end now removes a sandbox even when the session never recorded it, such as one a subagent sharing the sandbox opened first. Built-in providers keep a session's sandbox across rebuilds and open-option changes.
- `VercelSandbox` now runs on the public `defineSandboxProvider()` API, keeping existing sandbox names, session state, and snapshots. Breaking: a relative `workingDirectory` now resolves from `/workspace`, and `eve/sandbox/vercel` no longer re-exports `Drive`, so import it from `@vercel/sandbox` instead.

### Patch Changes

- Clearer sandbox error messages. Sandbox errors now say what went wrong and how to fix it, for example when the build and the runtime select different providers, a prepared template is missing, a session's sandbox came from another provider, or the sandbox file does not export its environment.
- Fix discovery of extension mounts written as `export { default } from "<pkg>"` inside a packaged extension, which `eve extension build` compiles to `import x from "<pkg>"; export { x as default };`.
- `eve dev` memory no longer grows with every save. Each rebuild now compiles and bundles your agent in a short-lived child process, and each new version of your code is served by a fresh worker, so old copies of authored modules no longer stay loaded. Modules imported by relative path now keep their package's `sideEffects` setting, so identical source bundles the same way on every save; in `"type": "module"` apps, default imports of older CommonJS packages that set `__esModule` now follow Node's rules. Thanks @callicles for reporting this in #5203.
- `eve dev` now rebuilds once per edit to a source-backed workspace extension. Before, the temporary `.eve-extension-build-*` files from the extension build started a second, unnecessary rebuild.
- The Discord channel can now answer DMs, mentions, and thread replies. `discordChannel({ gateway: {} })` accepts messages forwarded from the Discord Gateway, and `experimental_runDiscordGatewayRelay` from the new `eve/channels/discord/gateway` entry point holds that connection, for example in a Vercel Daemon. In text channels, a mention starts a thread that holds the conversation, and a reply to any bot message continues the session that posted it; set `gateway.startThread: false` to answer in the channel, or return `conversation` or `startThread` from `gateway.onMessage` to decide per message. `defaultDiscordMessageAuth` gives a message's author the same principal `defaultDiscordAuth` gives them for commands and button presses.
- `eve add channel/discord` now first asks whether people reach the agent through DMs, mentions, and threads, or a slash command. The first scaffolds the Discord Gateway relay in `daemon/`, registers it as a Vercel Daemon in `vercel.json`, enables `gateway` on the channel, turns on the bot's Message Content intent when Discord allows it, and skips registering `/ask`; the second keeps today's slash command setup and is what `--yes` picks. Non-interactive runs answer `discord-messages` with `"gateway"` or `"commands"`.
- The Discord channel now shows connection sign-ins. In a DM it posts the sign-in link and any confirmation code; in a server it posts a **Sign in** button that shows the link only to the person who has to sign in, in an ephemeral message. The message updates once the sign-in completes or is cancelled.
- `DockerSandbox` now runs on the public `defineSandboxProvider()` contract. Container names, recorded session state, and template image references stay the same, so running sessions and prepared images from earlier builds keep working. A few behaviors change: `sandbox.delete()` removes the session's container by its session-derived name, honors the caller's `abortSignal`, and succeeds when the container is already gone; eve normalizes relative paths such as `logs/../out.txt` to `/workspace/out.txt` before they reach the container; and a Docker environment's `prepare` callback is typed with `DockerSandboxSession`.
- A dynamic model resolver's `step.started` event now carries the index of the step it selects a model for. From the second step of a turn on, it used to carry the previous step's index, so per-step work keyed on `stepIndex` was attributed to the wrong step.
- A dynamic skill that stops returning `files` but is still returned now keeps the files already written to the sandbox, so files the sandbox provides another way, such as from its snapshot, stay in place. If you dropped `files` to take files away from some callers, stop returning the skill for them instead: a skill the resolver stops returning still has its files removed. On Vercel Sandbox, eve now writes a dynamic skill's files in one batch, with one path lookup and one upload instead of two round trips per file.
- `eve eval` artifacts now record each eval's `startedAt` and `completedAt` in `summary.json`, `results.jsonl`, and the per-eval detail file.
- An eval's `derived.usage` now takes each session's latest usage by time. An eval that captured a session again with an earlier snapshot reported that snapshot's lower total. Its `costUsd` is now absent when a counted session reported no cost, instead of summing only the sessions that did.
- Validate idle session state inside the workflow before starting a deployment handoff, avoiding unnecessary successor starts when durable work is still pending. Preserve inbox ownership and the original session stream throughout the move.
- Fix repeated horizontal rules and question text accumulating in terminal scrollback during human-in-the-loop prompts. Question and approval drawers now fit small terminals, keeping the focused choice or text editor visible.
- Avoid an extra setup command when creating a Vercel sandbox from a prepared snapshot of the standard eve image without Drive mounts. eve now checks the base runtime again after authored preparation, so a `prepare` callback that breaks it fails the build; existing sandboxes, resumes, custom images or sources, Drive mounts, and sandboxes without a prepared snapshot keep their setup checks. Vercel templates rebuild once so every snapshot has passed the new check.
- A session whose sandbox is gone (for example after a removed Docker container, a deleted Vercel Sandbox, or a deleted just-bash session directory) now starts a fresh sandbox on its next `ctx.getSandbox()`. Previously every sandbox call in that session failed with the same resume error until the session ended. Thanks @bradhallett for reporting this in #5113 and @moinulmoin for the just-bash case in #4440.
- New sessions start their first model step sooner, and later turns no longer wait for their cancellation hooks to register before their first step. Thanks @Lukavyi for reporting the startup latency in #876.
- The Linq channel now rejects inbound webhooks with a 401 whenever its webhook verifier returns any falsy value, including the `null` that `vercelOidc()` returns for a missing or invalid token. Previously only `false` rejected a request, so Vercel Connect setups without a `signingSecret` accepted unsigned webhooks.
- Self-hosted `eve start` servers now reject requests to `/.well-known/workflow/v1/flow` that did not come from the server's own workflow queue, so a client can no longer forge a workflow delivery with a chosen run context or principal. Startup always recovers pending and running local workflow runs through the authenticated queue, ignoring `WORKFLOW_LOCAL_RECOVER_ACTIVE_RUNS`; queue deliveries must stay on the process that enqueued them.
- Export `agentWithModel` for `agent/tools/agent.ts` to opt into a root-copy tool whose model-facing input selects the AI Gateway model for each task.
- OpenAPI connection tool calls now follow redirects only within the base URL's origin. A redirect to another origin is returned as the tool result, with its target in `location`, instead of followed, so credentials in custom headers, such as an `apiKey` security scheme's header, no longer reach the redirect target. A same-origin redirect loop now fails after 10 hops with an explicit error.
- Compaction summaries now run on the AI SDK model instance set as `compaction.model`. Before, a direct model instance there was ignored and summaries ran on the agent's top-level `model`.
- Compiles now prune `node_modules/.cache/eve/authored-modules` in the background, deleting cached bundles that no running eve process can still import, so the directory no longer grows without bound locally or in persisted Vercel build caches. Thanks @ryantbrown for reporting this in #847 and @kevludwig for reporting the Vercel build-cache impact.
- `server-only` and `client-only` imports now load as empty modules in every eve bundle, so tools, channels, workflow steps, and shared workspace packages that import them build and boot without `--conditions=react-server` or a direct dependency. Thanks @jakeleventhal for the original implementation in #3752.
- Update the bundled Workflow runtime to reduce redundant history reads during concurrent hook registration and avoid unnecessary input/output reads when resuming hooks. Include replay-ordering fixes and the local-world fix for deliveries that race a session handoff.
- Repair orphaned local tool calls in saved history before the next model request with an explicit unknown-outcome error. The repair never reruns tools or moves recorded results, and leaves provider-executed calls, approval requests and duplicate call IDs alone.
- Dynamic skills with supporting files are written into a sandbox that eve recreates after the old one was gone, at the start of the next turn. Before, the recreated sandbox got the same identity as the old one, so its skills were missing their files until the skill changed.
- The Linq and Photon channels' default webhook verification now only accepts Vercel OIDC tokens from the same project and environment.
- eve now runs every sandbox provider, including `DefaultSandbox`, directly on the public `defineSandboxProvider()` contract, and calls `connection.close()` when the step that opened a connection ends, so the next step resumes through a new connection. Server shutdown stops only connections eve still holds, so a custom provider that defines `close()` and runs remote compute should bound idle compute itself, for example with an idle timeout.
- Relative symlinks in an agent's `sandbox/workspace/` files, in skill packages, and in sandbox templates now stay relative in build output and in each sandbox session. Before, eve rewrote them as absolute host paths: `just-bash` sessions rejected them with `EACCES ... resolves outside sandbox`, and they did not resolve inside Docker, microsandbox, or remote sandboxes.
- Custom sandbox providers can declare `workspaceRoot` on a connection, and eve resolves relative paths, the default working directory, `resolvePath(".")`, and build-time workspace seeding from it; built-in providers keep `/workspace`. The `read_file`, `write_file`, `glob`, and `grep` tools now accept paths relative to the workspace root, and the workspace and skills prompt sections no longer name `/workspace`.
- `eve start` and the `withEve` production server for Next.js now fail fast with a clear "port is already in use" error when another process holds the port, instead of reporting a server they did not start and leaving the built server running in the background. Thanks @KingAmo for reporting this in #4938.
- A sandbox that was stopped and then ended no longer stays registered for server shutdown, so long-running eve servers stop accumulating ended sessions and shutdown no longer stops their connections again.
- Tools can now hand the model a file by URL. `toolOutputPart.fileUrl(url, { mediaType })` from `eve/tools` returns a `{ type: "file", data: { type: "url", url } }` content part from `toModelOutput`, so a large file such as a presigned PDF link reaches the model without being base64-encoded, staged into the sandbox, or stored in session history. Only `https:` URLs are accepted, and the URL must stay readable for the rest of the session because every later model call sends it again.
- Calling `prewarm()` on an existing session can now prepare an idle owner on the Vercel deployment accepting the request before the next message. Apps can trigger it when typing starts; it preserves the session, history, stream, and expiry, and does not block Send or run the model.
  
  Preparation uses the existing `POST /eve/v1/session/:sessionId` endpoint with no body or `{}`. Requests with messages or input responses keep their existing behavior.
- Each start or resume of a `workflow` tool program may now run up to 30 seconds of JavaScript and take up to 5 minutes in total, and time spent waiting for child agents counts toward neither limit.
- A `"use step"` helper in a workflow tool can now call `ctx.getSandbox()` to open the sandbox of the session that called the tool, on any sandbox provider, so a task can prepare files the session's later tool calls read. When the session had not recorded its sandbox when it called the tool, the step opens it with the owning session's sandbox definition; the step never owns the sandbox, and the session removes it when the session ends.



## v0.82.0 {#0.82.0}



### Minor Changes

- Breaking: replace `limits.maxInputTokensPerSession`, `limits.maxOutputTokensPerSession` and `limits.maxTokenCostUsdPerSession` with one `limits.sessionUsage` function. It receives the session's `total` usage and its `window` since the last approved continuation, and returns `true` when the limit is reached; Continue starts a new window. The default is 40M new input tokens (input minus cache reads) per window. Subagents now check their own window with their own `sessionUsage` or the root agent's instead of receiving a share of the parent's remaining quota. Sessions that can't ask now fail with `SESSION_USAGE_LIMIT_REACHED`, replacing `SESSION_TOKEN_LIMIT_REACHED` and `SESSION_TOKEN_COST_LIMIT_REACHED`.

### Patch Changes

- Attach the agent trace session ID to auto-instrumented child spans on Vercel so Agent Runs can include network and other third-party spans in a session trace.
- The session input-token limit now counts only new input (uncached input plus cache writes). Cache reads no longer count toward the limit, the grant after Continue, or the quota shared with subagents, so long cache-heavy sessions stop hitting continuation prompts for replaying their own history. Usage telemetry still reports raw input and cache totals. Providers that report no cache details count exactly as before.
- Allow authored workflow tools to select an AI Gateway model when they open a local session with `ctx.agent()`. The child keeps the target agent's other configuration, and the selected model applies for the session's lifetime.
- `eve eval` now runs while an `eve dev` session for the same agent is open, instead of failing with "A dev server is already running for this eve agent." The eval server keeps its runtime generations, local Workflow data, and server record in a per-run directory under `.eve/eval-servers/`, so it never swaps or prunes the dev session's state.
- Channel and session sends and responses now accept `idempotencyKey` to ignore retries across replay and owner handoffs. Photon supplies message IDs automatically; deduplication requires a shared Workflow World and only covers keys in the session's recent-key window.
- Fix a workflow tool task running twice when the session was interrupted while publishing `task.started`, for example during a slow `task.started` hook. The session now records each task's run before it publishes the event, so a retry only publishes `task.started` again and never starts a second run.
- `limits.sessionTimeoutMs` is now an idle timeout: the window restarts each time a turn settles, so a session in active use no longer ends 30 days after it was created. Idle sessions still complete when the window elapses, and the next channel message at their address starts a fresh session as before.
- Linq and Photon iMessage channels now tell the model when a message is a reply, and include the text of the message it quotes.
- The Photon and Linq channels can now pass tapbacks to the agent with a new `onTapback` hook, which can also answer the approval or question posted in the message the tapback is on, for example approving with a like. `channel.tapbackTool()` gives the model a tool that reacts to the latest message with a standard tapback or any emoji. Tapbacks stay ignored unless you opt in.
- `eve start --no-schedules` and `EVE_SCHEDULES_DISABLED=1` start a server that does not fire authored cron schedules, so only one process runs them when you scale out.
- Channel `send()`, channel message hooks, and a new `create()` on channel addresses accept `history` to add prior user and assistant messages, such as a stored transcript, as real turns. `create()` starts a session that waits for its first message and reports with `created` whether it did. A new `history.imported` stream event publishes added messages; the default client reducer renders them, and `transcriptReducer()` includes them. Slack `threadContext` now adds earlier replies as history when a message starts the thread's session; later messages keep the existing transcript.
- `eve build` and `eve dev` now evaluate a module shared by several tools, channels, or other authored files once per compile instead of once per importing file. Compile memory now grows with the code an agent actually has, not with the number of files that import it, so agents with many tools over a shared SDK or workspace package no longer run out of memory on smaller build machines. Authored modules transpiled to CommonJS with an `__esModule` marker, such as a `tools/*.cjs` file with `exports.default = …`, now also compile and run correctly instead of resolving to the whole `exports` object. On Windows, CommonJS authored modules can now `require()` eve and other external packages.
- Skip the final Slack reply when the message that started the turn was deleted, instead of letting Slack post it as a top-level channel message.
- Self-hosted `eve build` output now carries a build identity derived from its contents. eve exposes it to Workflow Worlds as `WORKFLOW_DEPLOYMENT_ID` unless that variable is already set, and records it in `eve build --profile` reports.
- Fix unnecessary `eve dev` runtime-generation changes when Nitro installs newer Rolldown versions. No-op rebuilds and environment-only reloads now keep the active runtime snapshot unchanged instead of treating bundler debug comments as runtime changes.



## v0.81.1 {#0.81.1}



### Patch Changes

- Fix activation trace-content markers to respect the resolved session policy, provider capture settings, and live audience ceiling. Metadata-only sessions now report withheld content accurately without removing content allowed by an explicit trace policy.
- A session keeps accepting messages during a deployment or compaction handoff, so the first message after a handoff reaches the model sooner and messages sent mid-handoff no longer retry or return `409 session_not_ready`; messages already waiting when a compaction finishes now run before the session moves. Sessions started on an earlier eve release still move to this release: their first move uses the previous handoff, and every move after it uses the new one. On Workflow worlds without hook force-claim support, sessions no longer move between runs, so their run history keeps growing for as long as the session lives.
- Cancelling a turn while the model is responding no longer marks its `agent.step` span as an error, so user-initiated stops stop showing up as failures in error tracking.
- Connections now accept the documented `auth.displayName` field instead of failing validation with `Unknown key "displayName"`.
- `agent.step` spans for AI Gateway model calls now record the Gateway's session affinity report: the session ID, where that ID came from, the affinity outcome, and the pinned and displaced providers. Use these attributes to match a step to its session in the AI Gateway logs Sessions view.
- The eve channel's `onMessage` can now read the request's `clientContext` as `ctx.eve.clientContext` and return its own `clientContext` to replace it for that turn, so the model sees server-checked context without it being kept in session history.
- iMessage voice notes now reach Photon agents. Photon's webhook leaves out a voice note's attachment id, so eve refetches the message by id to download it. Across Chat SDK channels, an attachment the platform gives no way to download now reaches the agent as a short note instead of being dropped, so an attachment-only message still gets a reply.
- `ctx.thread.postEphemeral()` on a fresh top-level Slack message now posts to the channel instead of an empty thread, where Slack hid it. Replies inside an existing thread stay threaded.



[Next](/changelog/page/2.md)