Released 2026-11-15 · Compare with 0.91.0
Breaking Changes
- Replace
agentWithModelwithagent({ models })fromeve/tools/agent, which lists the models a root-copy task may run on.
agentWithModellet the model pass any AI Gateway model ID and did not tell it which models exist.agent({ models })takes the same entries asauto()fromeve/models: a string entry is the description, and its key is the AI Gateway model ID; an object entry holds an AI Gateway model ID or an AI SDK model, with its description and optionalreasoning,modelContextWindowTokens, andmodelOptions. The model sees each key with its description and can choose only those keys. A call withoutmodelruns on the current model, andagent()with nomodelsis the default tool, with nomodelinput. A task keeps the model it started with, so a continuation can omitmodel. Copies and declared subagents never get this tool.
To migrate, replaceexport { agentWithModel as default } from "eve/tools/agent"withexport default agent({ models: { "<gateway-model-id>": "<when to use it>" } }).agentis now this function; re-exportdefaultfromeve/tools/agentto keep the default tool object. (#5959) - Every agent now gets a default
edit_filetool, the code extension dropscode__apply_patch, andbashresults and eve's system prompt now match pi's.
edit_file, exported fromeve/tools/edit_file, edits one sandbox file with exact text replacements matched the same way as pi'sedittool. The model sendspathand a list of{ oldText, newText }edits, each matched once against the original file, with a fallback that ignores trailing whitespace and normalizes smart quotes, dashes, and special spaces. Files that are not valid UTF-8 are rejected rather than rewritten, and a file keeps its mode, such as its executable bit, on sandboxes that write files with a default mode. Remove it withdefaultTools: falseor anagent/tools/edit_file.tsthat exportsdisableTool(); an authoredagent/tools/edit_file.tsreplaces it.
edit_filechanges existing files withoutwrite_file. If you disabled or wrappedwrite_fileto limit writes, or gatewrite_filein an approval policy, do the same foredit_file.write_filecan also overwrite a file the session read and then changed withedit_file, without anotherread_filecall. A change made by anything else since the read still requires one.
The code extension (eve/extensions/code) no longer mountscode__apply_patch, and theeve/extensions/code/toolsentry point is removed. Importgrepfromeve/tools/grepinstead ofeve/extensions/code/tools. Move an override of the old tool, whetheragent/tools/code__apply_patch.tsoragent/extensions/code/tools/apply_patch.ts, toagent/tools/edit_file.tsand spreadeditFilefromeve/tools/edit_file.edit_filetakespathandeditsinstead of a patch, so a wrapper that readsinput.patchneeds updating. Acode__apply_patch.tsfile that exportsdisableTool()failseve buildwithdisables a slot with no lower-precedence source; to keep agents from editing, exportdisableTool()fromagent/tools/edit_file.tsinstead.
installCodeTooling()no longer installs TypeScript or the post-edit diagnostics worker, andCODE_TOOLING_REVALIDATION_KEYchanged, so sandbox templates keyed on it rebuild once.
The code extension adds the workspace root'sAGENTS.md, orCLAUDE.mdwhen there is none, to the conversation, and its coding instructions now follow pi's tool guidance. The extension reads the file once per session, with one sandbox command on the first turn, which starts the sandbox. A file over 64,000 bytes is cut off with a note that tells the model where to read the rest.
A successfulbashcommand shows only its output, or(no output), and a command that exits non-zero ends with[exit code: N]and reaches the model as an error result.bashwaits 60 seconds by default before it leaves a command running in the background, and a truncatedstdoutorstderrnow names a file in the sandbox that holds its full output.
toolOutput.errorText(value)fromeve/tools, or a{ type: "error-text", value }literal, lets any tool'stoModelOutputshow the model a failure while the call still completes, so channels and hooks get the full output oncall.settled. The MCP channel returns such a result as its text withisError: true.
eve no longer adds a "Tool execution" note about parallel tool calls to every agent's system prompt. Tool calls in one response still run in parallel. Without the note, Sonnet 5.5 solved a concurrency task in 93% of replayed eve-code runs instead of 75%, matching how pi, which runs tool calls in parallel without telling the model, performs.
Thanks @badlogic for pi, whose MIT-licensededittooledit_fileadapts. (#5892) - eve 1.0 puts stable APIs under semantic versioning: they change incompatibly only in a major release, and a deprecated API keeps working until the next one.
The stability policy lists which APIs are stable and which are experimental. To move an existing project, follow Upgrade to 1.0. (#5620) - The code extension (
eve/extensions/code) no longer mounts itscode__greptool, which removes about 1.6K characters of tool schema from every model step.
To keep a structured search tool, runeve add tool/grep, which writesagent/tools/grep.tsre-exportingeve/tools/grep.eve/extensions/code/toolsstill exports the samegrepdefinition. Delete anagent/tools/code__grep.tsfile that exportsdisableTool(), becauseeve buildnow rejects it withdisables a slot with no lower-precedence source. Anagent/tools/code__grep.tsoverride that spreadsgrepkeeps working as your own tool namedcode__grep. (#5815) - The code extension (
eve/extensions/code) no longer adds the read-onlycode__workersubagent, andcode()rejects theworkeroption.
To migrate, removeworkerfrom yourcode()mount and delegate with the built-inagenttool. If anagent/tools/agent.tsoverride disablesagentso delegation goes tocode__worker, delete the override. A mount that still passesworkerfails withInvalid extension config: eve-code no longer ships a worker subagent; delegate with the built-in `agent` tool and remove the `worker` option.
Thecode__reviewskill starts a fresh-context agent with a no-edit audit brief when one is available and otherwise audits in the current session. Thecode__lookup-agent-runskill and the internaleve/internal/code/prwatchexport are removed. (#5800) - A dynamic tool no longer replaces a static tool of the same name: the static tool keeps the name and eve logs an error, as it already did for two dynamic tools with the same name.
To change a tool for some sessions only, define it only in a dynamic file that returns the usual version to the other sessions.
Agents whose only tools are dynamic now get the parallel-calls note in their system prompt, and the$eve.tool_countspan attribute counts the tools offered to the model rather than the tools the agent declares. (#5638) - New sessions now claim an address as they start, so racing first messages to a channel address reach one session, keyed sends and
create()respond without waiting for the session to boot, and a session accepts commands as soon as it is created.
Previously, two unkeyed first messages to the same new address could each get a receipt naming a different session: the losing run forwarded its message and exited, but its caller kept the dead session's ID. A cancel orend()sent by session ID before the session finished booting was answered with "no active turn" or "no active session" while the session kept running, and an early send had to retry409 session_not_ready. A send by session ID to a session that is shutting down now gets409 session_not_activeat once instead ofsession_not_readyretries.
eve now requires a Workflow world with atomic start hooks: the local world, Vercel Workflow, or@workflow/world-postgres5.1.1 or later. On another world, starting a session fails with an error that names the requirement. Upgrade@workflow/world-postgresand run itsbootstrapcommand before deploying this release.
A session can no longer move to this release from a deployment on eve 0.81.0 or earlier, which released its addresses before handing off. Finish or end those sessions before upgrading.
useEveAgentand the other framework bindings now sendend(),clear(), andcompact()called while the store is still creating its session to that session, instead of throwingSessionNotActiveError. (#5948)
Features
- Agents can now be published as Agent2Agent (A2A) v1.0 servers with
a2aChannelfromeve/channels/a2a, so other agents can discover them from an Agent Card and delegate durable, streaming tasks over JSON-RPC. (#5693) - Set
approvalinagent.tsto gate every tool, connection, and subagent call from one policy.
The agent's policy runs beside each entry's ownapprovaland the stricter result wins, so it can add a gate but never remove one. Subagent sessions inherit the root agent's policy. Thanks @kingztech2019 and @taoufik-ia for the proposals in #145 and #2673. (#5793) - Record an
agent.approvalspan for every wait on a person, including questions, budget prompts, and connection sign-ins, not just tool approvals.
agent.approval.kindistool-approval,question,budget, orsign-in. A wait sits under the tool call it's about, or under the turn when no call owns it, and a sign-in names its connection ineve.connection.name. Instrumentation providers now receive sign-ins oninteraction.openedandinteraction.settled, withsignIn.namenaming the connection or tool; the sign-in URL and code stay out of the event. Questions and sign-ins from workflow tools such asask_questionnow reach providers too, reported by the session that owns the tool call; a request a subagent asks is still reported once, by that session.@vercel/agent-runsaddsTurnOperation.approvalandfindApproval, and an optionalkindandconnectionNameon approvals. (#6004) - Preselect an option in a
display: "select"question by passinginitialOptionIdtoctx.ask.
Slack, Discord, Microsoft Teams, and theeve devterminal UI start with that option selected, and ACP clients receive it as the form field's default. On Slack and Discord, a Use button submits the preselected option, because those platforms send nothing when a person keeps the current selection. WheninitialOptionIdmatches none of the question'soptions,ctx.askthrows aTypeError. (#6202) - The provided
bashtool accepts an optionaltimeoutin seconds, so the model can wait up to 120 seconds for a build or test suite before the command keeps running in the background.
Calls withouttimeoutstill wait 30 seconds. Values above 120 wait 120 seconds, and values below 1 wait 1 second. A command still running after the wait returnsstatus: "running"as before. (#5813) mcpChannelaccepts aplainHttpoption for plain HTTP requests from a TLS-terminating proxy or a private network, which were otherwise refused off loopback. (#5700)- Add
ctx.conversation.space, which names the place a conversation happens, such as a Slack channel, so tools, approval policies, dynamic values, and memory scopes can share data per place.
Slack, Discord, Teams, Telegram, Linq, Photon, and Chat SDK channels report a space with a stableidnamespaced by platform and workspace, atypeofdirectorshared, avisibilityofpublicorprivatewhen the platform says, and aworkspaceIdwhere the platform has one. Custom channels report theirs with a newspace({ state })hook besideaudience. Tools and memory scope resolvers can now readctx.conversation, which dynamic values already had. (#6111) - Add the experimental
eve/experimental/extensions/custom-skillsextension, which lets the people talking to an agent save their own versioned skills, for themselves or shared with everyone in a channel or group chat.
Each skill has immutable versions and one live version, with drafts, publish and rollback, andalways,on-demand, ordeferredapplication modes saved per version. A validator and an approval rule you can replace decide which descriptions and instructions are accepted and which changes run, ask a person, or are refused, and the approval card shows the content that would go live. Shared skills follow the conversation'sctx.conversation.spaceon Slack, Discord, Teams, Telegram, and Chat SDK channels. Every skill has a stable ID beside its name. Skills are stored in anyeve/memory/filedocument backend, Vercel Blob by default, in a documented, versioned layout whose index lists every scope for admin views, or in your ownSkillRepositoryfromeve/experimental/extensions/custom-skills/repository;eve/experimental/extensions/custom-skills/policiesexports the built-in scopes, validator, and approval rule to compose your own. (#6106) - Dynamic schedules'
authandruncallbacks receive aschedulehandle that disables or deletes the schedule that fired, andauthcan return only{ attributes }to run as the stored creator.
Anauththat returnsnullnow fails the occurrence permanently: on Vercel the occurrence is acknowledged without redelivery andoccurrence.failedfires once, instead of after ten deliveries. The same applies whenauthreturns a principal other than the creator or a value of another shape. An error thatauththrows is still retried. If yourauthturns a failed lookup intonull, make it throw instead, or an outage will fail occurrences without a retry.
The handle and theauthresult are exported asScheduleHandleandScheduleAuthResult. (#6211) - A dynamic schedule's
runno longer starts its sessions again when the provider retries an occurrence.
Ato().send()without anidempotencyKeynow takes one from the occurrence and the message, so the retry reaches the session the first attempt started. Before, each retry started another session unlessrunpassed its own key. A message that differs between attempts still starts another session; pass anidempotencyKeyto keep it to one. (#6358) - Add an optional
idto the experimentaldefineDynamicSchedules, so a schedule collection keeps its stored schedules when its file is renamed or moved.
Withoutid, the collection's name still comes from its path underagent/schedules/. To move a collection, setidto its old path-derived name. A collection that a mounted extension contributes uses itsidas written, without the mount prefix.
eve buildnow fails when two collections, or a collection and a static schedule, in one agent resolve to the same name. A tool file that replaces or disables a collection's tools is named for the resolved name,agent/tools/schedule__<name>.ts. (#6212) - A dynamic schedules definition can declare named
scopes, for one kind of schedule with more than one owner.
scopestakes the place ofscope. The definition still offers one set of management tools, and each tool takes ascopeinput that names the scope to act in. A scope can set its owndescription,preparePayload,run, andapproval, and anidthat keeps the schedules an earlier definition stored.schedules(definition, { scope })binds one scope from code. A definition with a singlescopeis unchanged. (#6360) - A dynamic schedule's
preparePayloadreceives the schedule's timing ascontext.expression.
It is the timing the caller passed, or the stored timing when an update replaces only the payload, sopreparePayloadcan tell a recurring schedule from a one-time one without a payload field for it. (#6359) - Clarify the experimental dynamic schedules types and error messages, and deprecate the top-level identity fields of
ScheduleOccurrenceEventin favor ofoccurrence.
ThescopeandpreparePayloadcontexts are now exported asScheduleScopeResolverContextandSchedulePreparePayloadContext. No fields were removed and runtime behavior is unchanged. (#6213) - Dynamic schedules reject a cron expression that Vercel Schedules can't run before the write is prepared, so a model's call fails before a person is asked to approve it.
Vercel Schedules takes numeric fields only, and not both a day of the month and a day of the week. An expression that breaks these rules, such as one withMONorJAN, now fails with an error that says how to write it.eve devapplies the same rules. A customScheduleProvidercan implement the optionalvalidateExpressionto check timing the same way. (#6357) defineDynamic()inagent/tools/can return adefineWorkflowTool()held by a top-levelconst, so a workflow tool can be offered only on some model calls.
Its entry point can be written inline or reference a top-level"use workflow"function. The build fails when a workflow tool's entry point lacks"use workflow"or the tool is created inside the dynamic function. (#6235)- Add the
eveVite()plugin fromeve/viteto run eve agents alongside any Vite app in development,vite preview, and Vercel deployments.
eveSvelteKit(),eveTanStack(), and the Nuxt module now share its agent discovery and Vercel services, so all of them mountagents/workspace members at/eve/<name>/v1/*. The SvelteKit plugin no longer setsEVE_BASE_URLin the dev server process; set it yourself if your server code reads it to reach the agent. On non-Vercel hosts, the Nuxt module proxies each workspace member to its own local server on consecutive ports fromEVE_NUXT_PRODUCTION_PORT(default4274), or to/eve/<name>/v1onEVE_NUXT_PRODUCTION_ORIGINwhen set. (#6097) eve/eventsexportscreateStreamChecker, which checks a stored session stream against its lifecycle rules.
Run it over a stored or recorded stream to find lines that break the lifecycle rules, such as a turn that settles twice or a fact that names something never introduced. ItsStreamChecker,Violation, andViolationRuletypes, and theStoredLine,CommitLine, andProgressLinetypes it reads, are exported beside it. (#5834)- Add optional IANA timezones to fixed schedules so jobs can keep a local time across daylight saving changes.
SettimezoneindefineScheduleor Markdown frontmatter on Vercel and self-hosted Node servers. Omitting it preserves the host's existing behavior. Other Nitro presets reject explicit timezones. (#6311) executeGitHubShellnow throwsGitHubCommandInputErrorwhen a command's own input is refused, so a custom GitHub tool can tell the agent's mistakes from real failures.
Shell syntax, an invalid repository, aworkingDirectoryoutside the workspace, agh-signed-commitdirectory that is not a repository root, and a missing--body-fileused to throw a plainError, like a missing configuration or an empty Connect token. Detect the new error withisGitHubCommandInputError(error)fromeve/extensions/git/sandbox; its messages are unchanged. (#6181)- Add
label: falseto keep a tool's calls out of activity, such as emoji reactions.
Channels show no status for these calls, and a call doesn't end a quiet turn's silence, so a deferred Slack turn that only reacts and ends withno_replystays silent. The call'scapabilityand its message part fromeve/react,eve/vue, andeve/sveltecarryhidden: true, andshowsActivity(call)fromeve/eventsapplies the same rule in custom renderers. (#6017) - Add Slack's
action_tokentodefaultSlackAuthas theaction_tokenattribute, so tools can call the Real-time Search API without channel code.
eve also exposes the token asmessage.actionToken, read from the top level of the event or fromassistant_thread, where Slack sends it in app threads. (#6088) - Slack tool approvals now render as one card that holds the prompt, the tool input, and the Approve and Deny buttons.
The card replaces the separate approval card and collapsed Tool input block. It lists up to 10 top-level input fields within a fixed size budget, and a batch of large approvals splits across messages, so a click's callback stays bounded however large the input is. Approvals without input keep the compact card. An answered approval keeps its input preview as a record of what was approved, where eve used to delete the separate tool-input message when the request ended.
If you callrenderInteractionBlocksfromeve/channels/slack, an approval with tool input now returns onecontainerblock whosechild_blockshold the input preview and anactionsblock, instead of acardwithactionsfollowed by a Tool input container. Code that readsactionsor stampsblock_ids on interactive blocks should also look insidechild_blocks. (#6271) - Slack's
approvalChannelaccepts"ephemeral"to show an approval orctx.ask()question only to the person who started the turn, in the thread.
Everyone else sees aWaiting onnote naming that person, which shows the outcome once the request ends. The card needs only thechat:writescope and keeps the conversation in the thread, unlike"direct-message". A click replaces the card with the answer, because Slack can't edit an ephemeral message later. (#6270) - Slack sends a person's edit to a message the agent serves to that thread's session, as a
<slack_message_edit>with a diff of the changed lines and the full edited text, andslackChannel({ onMessageEdited })decides which edits reach the agent.
An edit follows the channel'sturnPolicylike any message: by default it joins a running turn, and if the agent already replied, it starts a new turn, which shows no thread status until its first tool call finishes; add theno_replytool so the agent can stay quiet when an edit changes nothing. By default, eve sends edits to DMs, code channel messages, and messages that mention the agent before or after the edit. With an authoredonAppMention,onDirectMessage, oronMessage, edits need their ownonMessageEdited, so they can't skip those hooks' checks; until then they go toonEventor are dropped.
The generated Slack app manifest now subscribes to themessage.channels,message.groups,message.im, andmessage.mpimevents and adds thechannels:history,groups:history,im:history, andmpim:historyscopes, which Slack requires to send edits. Reinstall the Slack app to grant them. With these events, the default handler also answers DMs without extra setup, and an authoredonEventreceives every message event in channels the app has joined. (#5796) - Slack message hooks can return
status: "deferred"to keep a message's turn quiet until a tool call finishes, andguidanceto tell the model how to treat that one message, so an agent can follow a thread and stay silent withno_replywhen a reply isn't meant for it.
status: "deferred"skips thereceivedacknowledgement. Mentions and DMs outside code channels get that acknowledgement before their hook runs, so for them it keeps only the rest of the turn quiet. A message that isn't deferred and joins the turn shows the status again. eve addsguidanceas a<guidance>block inside the message's<slack_message>or<slack_message_edit>block, after the metadata and before the content. The Slack docs show how to follow threads the agent already serves withonMessage.
Message edits now go through an app's own message hooks. Without an authoredonMessageEdited, an edit goes to the hook a new message of the same kind would reach:onDirectMessage, thenonMessage, for DMs;onAppMention, thenonMessage, for messages that mention the agent;onMessage, thenonAppMention, in code channels; andonMessagefor other messages. Without those hooks, the built-in defaults send edits to DMs, code channel messages, and messages that mention the agent before or after the edit, and drop the rest. Edits are always quiet and ignorestatus, and an authoredonEventstill comes before this default. The newctx.editis set while a hook decides an edit.
In 1.0.0-rc.2, an authoredonAppMention,onDirectMessage, oronMessageturned off edits unless the app also definedonMessageEdited. Those hooks now also run for edits in threads that have a session. If a hook has side effects, such asctx.send(),ctx.end(), or a decision model call, return early whenctx.editis set. To keep edits off, defineonMessageEditedand returnnull. (#5801) - Slack renderers can handle
call.inputto show a tool call's arguments while the model is still writing them.
This lets a renderer post a draft of what a call will produce, such as a card, and edit it as the arguments stream in. eve's default rendering ignorescall.input, so existing channels behave the same. (#6112) - Agents deployed to Vercel, including agents added to an app with
withEve, now run schedules with Vercel Schedules through a private function instead of Vercel Cron Jobs.
Each Vercel schedule is named after its file, such aseve.billing.sweepforschedules/billing/sweep.ts, andwithEveagents add the agent's name, such aseve.billing.heartbeat. Building awithEveproject requires Vercel CLI 65.14.0 or later. (#6087) defineWorkflowTooltools with anexecuteentry point now acceptendsTurn, so a workflow that waits for the user can end the turn without a model reply.
Passtrue, or a function that receives the call's output.taskandserveentry points still reject it.
Thanks @matchai for requesting this, and @xcscxr for the implementation plan in #5337. (#6336)- Add the Tavily MCP integration to the registry, so
eve add connection/tavilyconnects web search, extraction, crawling, and URL mapping through Vercel Connect OAuth. (#5731) - The provided
bashtool shows the model its output as plain text instead of JSON, so source code, diffs, and test logs reach the model without escaped newlines and quotes.
The model reads stdout, then any stderr after a[stderr]line, then a final[exit code: N]line; for a command still running, its instructions replace the exit code line. The tool'sexecuteoutput, its output schema, andcall.settledevents keep the structured fields. Authored code that reads the conversation, throughctx.messagesin tools orctx.messages()in dynamic capabilities, sees this text for newbashresults, and sessions keep the JSON results they already saved. Abashtool published over MCP sends the text incontent[0].text, and itsstructuredContentkeeps the structured fields. Wrappers that spreadbashkeep the plain-text view: a wrapper'sexecutethat returns a string reaches the model as text, and any other shape as JSON. (#5822) - Custom channels can answer pending approvals and questions from typed text, as eve's own channels do.
PassanswerTexttosend()when the model reads a wrapped message, such as one with a speaker prefix, and show the request a reply answers withnextPrompt(view)fromeve/events. (#5861) auto()fromeve/modelsandeve/tools/approvalacceptmodelOptions.providerOptions, anddecide()acceptsproviderOptions, so decision calls can set options such as AI Gateway'szeroDataRetention. (#5846)- Decision spans now name their turn and purpose, and record per-question results as
gen_ai.decision.resultswhen the trace records outputs.
decision <model>spans carryagent.turn.idandagent.decision.purpose(model-selection,tool-approval,agent-routing, orcustom), so Agent Runs can place a model-selection decision in a turn that is still running. Results follow the proposed OpenTelemetry GenAI decision conventions: choices, predicates, scores with their levels, and refusals, each keyed by the question's position. They are output content, recorded only when outputs are and dropped for any destination that declines outputs.AgentRun.decisionaccepts an optionalpurpose, and completing a decision withoutputrecords it as the results. (#6389) - Deployed agents start faster and use less memory, because hosted builds now include each installed package once instead of once per instrumentation file and once more for the agent's modules.
Before, when instrumentation files imported the same packages as the agent, every one of those packages shipped, loaded, and ran more than once on each cold start. In one production agent with five instrumentation files, the workflow route's bundle dropped from 34 MB to 22 MB and its cold start from about 2.6 s to about 1.8 s. (#5943) - Start eve commands faster by enabling Node's on-disk compile cache for the CLI process. (#6423)
- Make
eve devagents ready sooner by loading eve's vendored dependencies from its install instead of bundling them into every development host. (#6434) - Start eve commands and
eve devagents faster by resolving eve's internal imports directly instead of through Node's package.json lookup. (#6424) - Show the
eve devprompt sooner by loading only the startup draft's modules before the first paint. (#6433) - Make the
eve devagent answer its first request sooner by loading the published generation in the worker as soon as the server starts. (#6442) - Dynamic functions can read the session's sandbox with
ctx.getSandbox(), the same handle tools and hooks get.
eve runs dynamic functions before every model call, so read the sandbox insidectx.memo, keyed on what would change the files, such as the latest checkout call inctx.view.ctx.getSandbox()isn't available while choosing the model. (#5802) - Explain more prominently that
defineDynamicfunctions run before every model call, so network requests, database queries, API calls, and sandbox reads belong insidectx.memo. (#6278) - Add
EVE_EVAL_OIDC_TOKENto reach a protected Vercel deployment fromeve eval --urlthrough Trusted Sources. (#4894) - The code extension (
eve/extensions/code) sends a prompt about a third of its previous size (4,942 to 1,636 characters) that keeps only coding and safety rules, so agents spend fewer tokens on every step.
The prompt no longer assumes a chat product or sets consumer policy, such as brevity, asking one question, avoiding em dashes, omitting private references, or not rebasing. Agents that relied on those rules should state them in their ownagent/instructions.md. Agents publish or write to external systems only when the requester asks for it or for an outcome that requires it, such as a pull request. The prompt asks agents to edit files with the editing tool instead of the shell, and no longer namesapply_patchspecifically. The issue and design checklists moved into thecode__investigateskill. (#5805) - A new root session starts its first turn sooner: the workflow creates its initial state directly instead of in a separate durable step. (#6421)
- A turn reuses the cancellation and steering controls an earlier turn left unaborted, so a message that arrives right after a turn no longer waits for new abort hooks. (#6420)
- A followed session stream opens alongside its session check instead of after it, so its first lines arrive sooner. (#6418)
- Session stream reads skip the earlier-eve version check for sessions the server created or already found current, so they start sooner. (#6417)
- A turn settles without waiting for its model usage run attributes, which are now written behind it. (#6419)
- Bundle the server faster in
eve buildandeve devby resolving dependency imports and CommonJS path globals inside Rolldown instead of eve's JavaScript plugin hooks.
eve buildalso no longer repeats the authored module builds after sandbox prewarm. (#6209) - Anthropic models on AI Gateway now cache the system prompt across sessions, and can cache it for 1 hour.
eve addsgateway.cacheAnchorMessageIndex: 0next tocaching: "auto", so a resumed session whose cache expired reads the shared system prompt from cache instead of writing it again. An authoredcacheAnchorMessageIndex, orcachingset to anything other than"auto", is left as it is.
On Anthropic models, eve now sends the base part of the system prompt as its own system message with the cache breakpoint, and the sections that differ by session (dynamic instructions, tasks and approvals) after it. Sessions with different channel or user instructions no longer write the shared base again.
modelOptions.promptCache.anthropic.ttl: "1h"now also applies to Anthropic models through Gateway. eve then turns Gateway's automatic caching off, because Gateway ignores a 1-hour TTL under it, and places its own breakpoints for 1 hour, as it does on a directly called model. The default stays5m. (#6151) - Add
github.permissionsto the git extension's"app"config. eve mints each installation token with only those permissions, so a broker no longer has to re-mint a narrower token and rebuild the credential header for every GitHub host eve leases. (#5966) - Each wait for a
ghcommand's sandbox credential lock is recorded as anagent.github.lease.waitspan, withagent.github.lease.outcomeandagent.github.lease.attempts. (#6196) - New projects'
AGENTS.mdand the coding-agent setup prompt now point to guidance on keeping the deployed bundle small and cold starts fast. (#6079) - Hosted agents start faster: the bundled manifest is checked when the agent is built instead of on every cold start, the workflow driver code ships as plain text without an inline source map in production builds, and error-message formatters are created only when an error needs them. (#6047)
- Chat SDK, Discord, Telegram, and Teams now say who answered a question or approval when they edit its prompt, as Slack already does:
Approved by AliceorAnswered by Alice: Saturday.
Each channel records the person behind a principal when that principal sends a message or presses a button, then names them from the settlement's responder. Discord shows a mention, which doesn't notify anyone because the edit allows no mentions. Teams already named who pressed Approve; it now also names people who approve by text or answer questions. A prompt withdrawn without an answer, or answered by someone the channel never saw, reads as before. (#6110) - Speed up
eve buildandeve devby parsing each workflow source once and, when eve is installed, reusing eve's own workflow driver bundle across builds. (#6215) - Removed the Build an Agent tutorial from the docs, and the link to it from the README that
eve initwrites; the old tutorial URLs redirect to the matching guides. (#5717) - Publish
ghcr.io/vercel/eve-git, eve's default sandbox image plus the GitHub CLI (gh), and the same image to Vercel Container Registry asvcr.vercel.com/vercel/eve/git.
Each eve release pins one tag of it, exported asDEFAULT_EVE_GIT_SANDBOX_IMAGEfromeve/sandbox/dockerandVERCEL_EVE_GIT_SANDBOX_IMAGEfromeve/sandbox/vercel, and both fromeve/extensions/git/sandbox, andlatestmoves to the tag of the released eve package.
Pass the constant asimagesoinstallCodeToolingfromeve/extensions/code/sandboxfindsghand skips itsapt-getinstall, which takes about 7 seconds of a first build. A Vercel Sandbox session from a prepared snapshot of the eve-git image runs no base setup command, like the default image. The default image is unchanged. (#6246) - eve now targets Node.js 26: new projects pin
engines.nodeand@types/nodeto26.x, so Vercel deploys them on thenodejs26.xruntime, and the default sandbox image and generated Discord relay Dockerfile run Node.js 26.
eve still supports Node.js 24 and later. When eve updates thepackage.jsonof an existing project that pinsengines.nodeto another major, such as24.x, it now sets26.xand prints a warning. SvelteKit apps deployed to Vercel need@sveltejs/adapter-vercel6.3.5 or later to build on Node.js 26. (#6304) - Sessions store much less as conversations grow: each session step now returns its changed values as frozen immer versions of the values it was given, so Workflow stores each step's input as a reference and its output as only what changed, instead of a full copy of the history every step. (#6219)
- Slack
onInteractionactions now includeresponseUrl, the click'sresponse_url.
POST to it to replace or delete the message the click came from, including an ephemeral message, whichchat.updateandchat.deletecan't change. (#6247) webSearch({ provider: "tako" })selects Tako Search through AI Gateway, which returns web pages and Tako data cards with their rows in one call."tako"also works as afallbackforwebSearch({ provider: "native" }). (#5880)eve add channel/telegramnow offers guided setup with Vercel Connect or portable credentials.
With Connect, it stores the bot token in a Telegram connector and routes the connector's triggers to/eve/v1/telegram, so Connect registers and verifies the webhook. With portable credentials, it writes the bot token and a generated webhook secret to.env.local. (#5810)- Add
decision <model>OpenTelemetry spans fordecide, automatic model selection, and tool approvals, with policy-aware model, usage, cost, and failure metadata that distinguishes refusals from request failures.
A decision sits under the operation it runs in, or under the turn when model routing runs before the turn's first step.@vercel/agent-runsaddsAgentRun.decisionand an optionalAgentTelemetry.activeSpan, so a decision nests under a host span inside its operation but not under a host span from another trace, such as a workflow step. (#5349) - Session events can now record a call or a content part that its turn made without a model run:
call.requestedaccepts anownerof{ turnId }, andcontent.completedleaves outrunId, withscope.turnIdnaming the turn.
The fold, the client's conversation, and the Slack channel place both under their turn.ContentCompletedData.runIdis optional andCallOwnerhas a third variant in TypeScript, so code that readsrunIdas always present or switches over owners needs a default branch. Stream version 27 also now allows a later release to add call owners, and a reader treats a call whose owner it doesn't know as the session's. (#5771) - Fix
vercelBlob()fromeve/memory/file/vercelso a document whose key contains/can be read back after it is written.
Before, such a read returned nothing, so the next write tried to create the document again and failed because it already existed. (#6106) - Update the bundled Workflow runtime to 5.3.0 and create new runs with Workflow spec version 9, which drives each run from one orchestrator.
Workflow 5.3.0 lets parallel branches advance inline steps without waiting on slower siblings, reuses resolved hooks to skip token lookups on later resumes, and fixes a step that could be created but never run when two executions raced in one process. eve now setsWORKFLOW_SPEC_VERSION=9before it creates a world unlessWORKFLOW_SPEC_VERSIONorWORKFLOW_SEALED_LOGis already set. SetWORKFLOW_SPEC_VERSION=8to keep creating spec 8 runs. Existing runs keep their version. (#5860) - Update the bundled Workflow runtime to 5.4.0.
Workflow 5.4.0 resumes a parent run once when a child run finishes instead of polling in a step, honors abort signals when waiting for a run to finish on the Vercel World, and recovers Hook token claims left by a crashed process right away on the local World instead of after 30 seconds. (#5944) - Update the bundled Workflow runtime and worlds to the Workflow 5.5.0 release. (#6219)
Bug Fixes
-
A successful
endsTurncall now ends the turn even when the model calls other tools in the same step.
Those calls still run, including ones that wait for an approval, a sign-in, or a workflow, and the turn ends once they all settle, whatever their outcome. Before, the turn ended only when every call in the step could end it, sono_replycalled beside another tool started another model call whose text was posted as the reply. (#6371) -
eve's two unauthenticated callback routes now resume only the hooks they exist for, so a request that guesses a token can't resume a hook your code created with
createHook(), or an eve hook the route isn't for. (#6489)/eve/v1/callback/:tokenresumes only a call that waits for a remote agent's reply. eve now generates a random token for each message to a remote agent, which adds one workflow step to that message. Someone who knew the run's identifiers could compute the earlier token./eve/v1/connections/:name/callback/:attemptId/:tokendelivers a sign-in callback only to a session's inbox or to a workflow tool's own sign-in hook.
Both routes answer
404for any other token. Don't start acreateHook()token witheve:, because eve reserves that prefix for its own hooks.On Vercel, callbacks go to the current production deployment, but a workflow tool run or a task keeps running on the deployment that started it. Once production runs this release, a run on a deployment with an earlier release no longer receives a remote agent's reply, or a sign-in that a
"use step"function asked for, and its call keeps waiting. That includes a task a session keeps after it moves to the new deployment, for as long as the task lives. If your agent calls remote agents or signs in from workflow steps, end its sessions after production runs this release, and start new ones. A sign-in link from a session that still runs on eve 0.56 or earlier is refused too. -
Fix durable agent traces keeping every finished turn that called tools in parallel: each one stayed in the session's serialized context, so step inputs grew with every turn.
A checkpoint this process had already written, read back through another execution context, was treated as another process's write and forked the turn's trace tree; the stale copy then overwrote the tool completions and the checkpoint was never deleted. A replaced tree now also stops persisting. (#5835) -
AI SDK telemetry integrations such as Sentry's now receive model and
decide()prompts and responses whenever theotel()trace policy or any instrumentation file'stracePolicyallows content, without anotelIntegration()destination.
Starting withai@7.0.163, the AI SDK removes content from telemetry when a call disablesrecordInputsorrecordOutputs. Before this release, eve disabled both on every model call in apps without an OpenTelemetry destination, so a Sentry-only setup lost prompts, responses, and token usage. Apps that added an emptyotelIntegration({})only to work around this can remove it.
In apps without OpenTelemetry,decide()calls previously left these settings unset, so AI SDK integrations received decision content for every conversation. They now follow the same rules as model calls: content for public conversations and in development by default, and otherwise only when a trace policy allows it. (#6234) -
User-role instructions, static and dynamic, now join the conversation the same way: once ahead of the next turn's input, again when their content changes, and again after a compaction or clear removes them from the history.
A newer deployment that changes a static user-role instruction adds the new text to existing sessions instead of keeping the text the session started with. Sessions that already hold an instruction don't receive it twice. (#5638) -
Every eve build now reads
pathsaliases from the authored package's owntsconfig.jsonorjsconfig.json, and an asset import that leaves the authored package fails the build.
The Nitro host, authored module bundles, and the workflow driver share one resolver. The workflow driver no longer searches parent directories for a config, and an agent directory without its ownpackage.jsonuses the enclosing package's config in every build. Before, only?rawasset imports were checked against the package root; now plain imports such asimport notes from "../../notes.txt"are checked too. If a build fails with "resolves outside package root", move the file into the authored package or into the workspace package that imports it. (#5879) -
Let
auto()route messages longer than 16,000 characters using the configured decision provider's input limits.
The decider receives the full text of the turn's opening input and up to seven earlier user and assistant messages. Larger inputs can increase decision cost and latency. Provider input-limit errors use the configuredfallback, like other decision failures. (#6273) -
Model calls made by
decide()fromeve/ai, and so byauto()and approvalauto(), now count toward the session's usage andlimits.sessionUsage. (#5638) -
When a finished
bashcommand's output is truncated, the result again keeps the start of a very long last line and the lines before it.
The truncation note again gives the whole output's line count (showing last N of M lines), and memory stays bounded however much the command prints.
Thanks @zackleman for reporting this in #5925 and for the implementation plan this fix follows. (#6248) -
Limit MCP tool validation feedback to ten issues and 4096 characters, and stop published tools' JSON Schema validation at the first failure. (#6347)
-
Inline tool execution now requires permission from eve's approval gate.
When a person answers the same call more than once, eve uses their latest answer. (#5638) -
A cancelled sign-in is no longer asked for again in the same turn, and a scheduled run never asks for a sign-in.
When a new message cancels an open sign-in, later calls in that turn that need the same grant fail withreason: "sign_in_cancelled"instead of posting another sign-in prompt. A turn a schedule started, including a scheduled send into an existing conversation, fails calls that need a sign-in withreason: "sign_in_unavailable". In both cases the model is told to say the action needs that access. A later message from the person asks again. (#6003) -
eve now records which of its catalog tools a session has been offered in the same session state as its other definitions, rather than under a separate context key.
A session an earlier deployment ran still keeps every catalog tool it was offered. (#5638) -
A channel route whose path ends in a file extension, such as
/.well-known/agent-card.jsonor/robots.txt, now builds and serves its handler.
Thanks @mattcreager for reporting this and tracing it to the route module ids in #5742. (#5744) -
Under
eve dev, eve now throws if a tool call starts before its approval is accepted, or names a different approval as what cleared it. (#5638) -
Compacting a session between turns no longer repeats the last question after its answer, so the next turn's new message follows the summary and recent history instead of an already-answered question. (#5638)
-
Compaction now summarizes directly and must bring the input under half the context window on the provider's token count, so a long session compacts once instead of several times in a row.
It no longer caps old tool output first. A compaction whose result is still over the threshold on the next call skips the stage that fell short. (#6126) -
A context compaction's summary request during a turn now exports its own
chat <model>span under the turn'sinvoke_agentspan, with its token usage, cost, andai.settings.context.eve.compaction.request=summary, so traces no longer undercount compacting turns.
Model spans now also carryagent.turn.id.@vercel/agent-runsaddsTurnOperation.modelCallfor model calls a turn makes outside its steps.
Thanks @zackleman for reporting this in #5922. (#6251) -
Sessions that switch back to a model now check its retained token measurement as well as the latest measurement, reducing compaction between steps.
Different models' tokenizers can count the same history very differently. eve judged each call by the token count the previous call reported, so after switching to a model whose tokenizer counts higher, the history could cross the compaction threshold during the turn's first step and be rewritten before the next step, invalidating the prompt cache a second time in one turn. eve now keeps each model's latest measurement until history is rewritten. Before each call, eve uses the larger count after estimating additions from both the selected model's measurement and the latest measurement. A model without a retained measurement still falls back to the latest one. (#6186) -
Computer use installs again because the sandbox takes the Firefox ESR line Mozilla currently serves instead of requiring ESR 140, which Mozilla no longer offers.
The managed Firefox profile also skips the Terms of Use dialog that ESR 153 opens over the first page.COMPUTER_USE_REVALIDATION_KEYchanges, so templates that include it rebuild and drop the cached ESR 140, which no longer gets security fixes. Thanks @treydoe1 for reporting this in #5829. (#5831) -
Default scaffolded projects to
@vercel/connect@2.7.0and require^2.7.0for the optional@vercel/connectpeer. (#5733) -
Keep child questions and approvals answerable while a serving task remains active after replying to its original call.
Upgrading a session whose history was cleared or compacted also restores its dynamic user instructions before the next model call. (#5638) -
When a session stream write fails, the turn step now stops writing and fails at once, so Workflow retries it with a fresh stream, instead of retrying the model call, steering, or reporting a model call failure to the stream that just failed.
Previously, eve read a failed write as a model call error: it retried the provider request, logged that it was "parking session for retry by the user", and tried to write a failure that could never arrive. The retried step closes the model attempt the write cut asabandoned, as it does for any interrupted step.
Thanks @zackleman for reporting this in #5917. (#6264) -
Fix tool-stub validation for memory-only agents, mounted dynamic connection names, and sandbox skill files when an earlier definition starts offering a colliding skill.
The chosen model also remains visible to session code across separately bundled runtime modules. (#5638) -
Update eve's bundled dependencies, including the AI SDK, Vercel SDKs, Chat SDK, and MCP, to their latest releases, and OpenTelemetry to its latest 2.x releases.
eve now requiresai7.0.172 or later.
YAML frontmatter, eval data files, and OpenAPI specs now parse with js-yaml 5 and YAML 1.2 values. An unquoted date such as2024-01-02loads as a string instead of aDate, and a0bbinary literal such as0b101loads as a string instead of a number. The YAML 1.1 tags!!timestamp,!!binary,!!set,!!omap, and!!pairsare no longer recognized, and a mapping with a non-scalar key, such as? [a], throws.<<merge keys still work.
MCP connections over Streamable HTTP now fail when theserver/discoverrequest fails before the server answers, instead of retrying withinitialize. SetprotocolVersionDiscovery: falsefor a server that can't handle that request. Servers that answerserver/discoverwith a JSON-RPC error or an HTTP error status other than401still useinitialize, and servers that reject the protocol version with a supported legacy version still negotiate it. (#6378) -
eve devnow resolves a string agent model through a customglobalThis.AI_SDK_DEFAULT_PROVIDER, aseve startdoes, instead of routing it to the local AI Gateway connection. (#5789) -
eve devno longer answers every second request with an empty400 Bad Requestwhen the client sendsConnection: closeand the agent replies with a keep-alive response such as an MCP SSE stream, as happens behind thevercel devproxy. (#6298) -
Dynamic connection resolvers can exchange names within one evaluation without a transient collision, and namespaced tools and skills retain their full name-length validation. (#5638)
-
Dynamic values evaluated before a model call now see the task results and
[Tasks]note that call delivers, so a dynamic model can react to a background task's result in the same step. (#6185) -
Answer workflow tool calls from a model response that ended early (finish reason
lengthorother) as not run, like other skipped calls, instead of starting their workflows without deciding their approval. (#6010) -
Fix release asset uploads failing with 401 through the git extension's
ghtool.
The credential lease now coversuploads.github.com, not onlyapi.github.comandgithub.com. A 401 there was read as a revoked token and opened a sign-in for a user who was already signed in.
When Vercel Connect starts an authorization without a sign-in URL or device code, the user-scoped GitHub sign-in now fails withConnectionAuthorizationFailedErrorinstead of opening a sign-in prompt with no link. (#5852) -
A turn whose step fails every Workflow retry now settles
failedwith codeTURN_FAILED, a fixed message, and an error id, instead of the thrown error's class and raw message, which could carry prompt text or tool input.
eve's own log line for the failure records that error id and the thrown error's class, but not its message or details, and the recovery step's stored input carries only the class. Workflow's own step-failure log still includes the error's stack.
A turn cancelled while its failing step was between retries now settlescancelledand keeps its input in history, instead of settlingfailedwith the step's error.
Thanks @zackleman for reporting this and proposing the fix in #5915. (#6261) -
Update vulnerable dependencies and bound MCP tool input validation to prevent excessive memory use. (#6177)
-
Fix signed inbox handles so follow-up messages can skip repeated hook lookups when
EVE_INBOX_HANDLE_SECRETis set and the world supports guarded hook resumes. (#5904) -
Fixed a parent session crediting or refusing the wrong person's answer when several people answer a subagent's approval before the subagent settles it, including for remote and protocol 2 subagents. (#6165)
-
When AI Gateway cuts a model stream at its maximum duration, eve now retries it once instead of up to three times.
The error hint now says that eve already retried the request and suggests smaller turns or another model. (#6159) -
A
ghcommand whose lock was taken over after 10 minutes no longer clears the next command's GitHub credential when it finishes. (#6189) -
Subagents that share a sandbox no longer trigger spurious GitHub sign-ins when they run
ghcommands at the same time.
Theghtool's credential lease replaces the sandbox's network policy for the duration of one command. Leases were serialized per session, so sessions sharing a sandbox, such as parallel subagents, could replace or clear each other's credential mid-command; the stranded command got a 401 from GitHub, which asked the user to sign in again even though their grant was valid. Leases are now serialized per sandbox by a lock inside the sandbox, which works across processes. A command waits up to a minute for another to finish, then fails with a retryable error. (#6029) -
Reword the GitHub sign-in failure message so it says plainly that the person does not have access yet and how to get it. (#5998)
-
A workflow tool's question that reaches the session after its turn was cancelled no longer fails the session: eve drops it, and the next message starts a turn. (#5638)
-
Turns no longer resume a session's sandbox in the background when they start, so a turn that never uses the sandbox no longer wakes it; the first tool or file operation that needs it resumes it instead. (#6187)
-
Make local world stream reads scale with new chunks: a repeated
getInfoor cursorgetChunkson a long stream no longer reopens every earlier chunk file. (#5910) -
Fix local-world sessions that stalled after
eve startoreve dev --resumerestarted mid-turn: a turn waiting on a timer, such assleep, now wakes on time, and a step that was running when the previous process stopped runs again right away instead of after about 14 minutes.
The timer fix applies to spec 9 runs, which eve now creates by default. The step fix applies to spec 8 runs, including every session created before eve moved to spec 9. For those runs, the interrupted attempt counts toward the step's retries, so a workflow tool step withmaxRetries: 0that was running when the process stopped fails on restart instead of running again. Run one process per.eve/.workflow-datadirectory: recovery treats steps started before it booted as abandoned. (#5873) -
Memory slots and schedule collections now offer their tools themselves, so agent info no longer lists them as generated dynamic tool files.
A tool file atagent/tools/<slot>.tsoragent/tools/schedule__<name>.tsstill replaces those tools, anddisableTool()there still removes them. Sessions and approvals parked across the upgrade keep working. (#5638) -
Name the memory store on memory provider tool calls, so a trace query by
gen_ai.memory.store.idfinds a scope's tool reads and writes as well as its recall and capture.
Theexecute_toolspan of a memory provider tool, such asprofile__save, now carriesgen_ai.memory.store.idandagent.memory.slot, matching thesearch_memoryandupsert_memoryspans of the same slot. The store ID is the slot's opaque scope key, so it is recorded whatever the trace policy captures.@vercel/agent-runsadds an optionalmemorylifecycle toActiveOperationon tool operations to record it. (#6147) -
Agent builds now build a workspace extension that only another workspace extension mounts or depends on, instead of failing with a missing compatibility manifest on a clean checkout. (#6160)
-
Keep a session open when its requests outgrow the compaction threshold or the model's context window.
When the agent's instructions, tools, memory, and context leave no room undercompaction.threshold, eve logs a warning and compacts against the model's context window instead of ending the session withCOMPACTION_FAILED. When they don't fit the window either, only the turn fails withCOMPACTION_FAILED. When a provider rejects a request as longer than the model's context window, only the turn fails withMODEL_CALL_FAILED, and the session can receive another message.
Thanks @zackleman for reporting this in #5921. (#6262) -
The Vercel project overview card now shows the agents' tools, schedules, and connections for a Next.js app that hosts an
agents/workspace throughwithEvefromeve/next.
Duringnext build,withEvenow writes the workspace's.eve/agent-summary.jsonindex, the same index thatwithEvefromeve/vercelwrites since #5710. Standalone agents and agents configured with theagentsoption do not change. (#6163) -
A
HEADrequest to a channel path that declaresGETbut notHEADnow gets405 Method Not Allowedwith anAllowheader instead of404, and theGEThandler doesn't run.
DeclareHEAD()on a path to answerHEADrequests there, under any parameter name:HEAD("/items/:itemId")answers forGET("/items/:id"). Paths that already declareHEAD(), such as/and/eve/v1/health, are unchanged. On a CORS-enabled path, the405carries the CORS headers, so a browser can read it.
eve buildandeve devno longer merge the app root'snitro.config,.nitrorc, or.envfiles into eve's own Nitro host, and no longer serve an app-rootserver.*orindex.htmlas a catch-all in front of eve's routes. A Nitro app that shares its root with an eve agent, such as a TanStack Start host, keeps its Nitro configuration to itself. eve still loads.env,.env.local,.env.development, and.env.development.localforeve devthrough its own environment handling, and still serves files in an app-rootpublic/directory as static files.
eve devnow rebuilds its host when a connection turns on events or an extension mount changes the package export it imports. Before, those edits reused the running host, so the event receiver route or the new mount stayed missing untileve devrestarted. (#5692) -
Upgrade Nitro to 3.0.261103-rc, the first Nitro 3 release candidate eve builds on.
eve now declares Rolldown 1.2.16 itself and hands that copy to Nitro, so a plain npm install builds without relying on another package to provide Rolldown, and Nitro never installs a package into your app on demand. Importingnitro/storage,nitro/kv, ornitro/databasefrom agent code now fails the build with an explanation instead of pulling in storage drivers. A request with a method its path doesn't declare, other thanHEAD, now gets405 Method Not Allowedwith anAllowheader instead of404.eve devruns on env-runner 0.3, and a stoppedeve startserver runs Nitro's close hooks and exits on its own.
Thanks @pi0 for the investigation in #5167. (#5870) -
Background work a channel route registers with
waitUntilwhile its streamed response is still being sent now runs to completion on hosted platforms, instead of being dropped.
Channel routeparamskeep encoded path separators (%2Fand%5C) encoded, so a param can no longer contain a/or\that the request path never had. Other percent-encoded characters are still decoded, so/files/caf%C3%A9givescafé; a handler that expected%2Fdecoded to/must now decode it itself.
Agent text that mentions a Nitro build constant such asimport.meta.devnow reaches production builds unchanged, instead of being rewritten to its value or failing the build. Skill files are embedded in the server bundle instead of Nitro server assets, so hosted output no longer ships Nitro's storage layer unless authored code imports Nitro storage itself.
A channel path that declares bothGET()andWS()now accepts WebSocket upgrades, which theGETroute used to answer as a plain HTTP request. WebSocket routes register forGETonly, the method an upgrade uses. Because one handler serves both, the two routes must name their path parameters the same way;eve buildrejects a pair such asGET("/rooms/:id")andWS("/rooms/:room").
Vercel service builds keep the schedule consumer function and its queue trigger, so dynamic schedules deliver their occurrences.
eve startnow runs the server's shutdown hooks, such as flushing instrumentation, when it stops the server in an environment that setsCI. The built server no longer inheritsCIorNITRO_UNIX_SOCKETfromeve start.
A server without eve's workflow program runtime installed now fails a generated workflow program with an error that explains why, instead of importing the runtime from a path hosted output can't resolve. (#5698) -
eve now compiles an agent's dynamic tool, skill, connection, and instructions files, hooks, and memories to one list in the compiled manifest, and runs them as definitions of one shape.
Rebuild agents after upgrading; authored files don't change. (#5638) -
The discovery manifest in
.eve/discovery/agent-discovery-manifest.jsonnow lists an agent's authored files in onesourcesarray, with each file's kind given by its path, instead of one array per kind. (#5638) -
Session history now changes in one place, which checks every message as it joins, and under
eve devfails a step whose tool results don't follow the calls they answer.
A turn that fails after the model delivered its structured reply keeps that reply in history instead of an unansweredeve__replycall. A compaction whose summary model fails to resolve now appears on the stream as a failed compaction instead of failing the turn before it starts. (#5638) -
The model no longer sees an "awaiting approval" note in history after the approval it describes is answered or dropped, because eve now tells each model call about pending approvals from the session's current state instead of writing a note into history when the call parks. (#5638)
-
An agent or
servetool call whosetaskIdis the placeholder string"undefined"or"null"now starts a new task instead of failing withUNKNOWN_TASK.
Some models send these placeholders instead of omitting the optionaltaskId. An emptytaskIdalready started a new task. (#6183) -
Sessions that started on eve 0.69 through 0.83 and delegated to a subagent now move to the new deployment instead of staying on the old one until they end.
An idle resumable task no longer keeps such a session on its earlier deployment: the move ends the task's old run, and the model starts a new task on the current build when it needs one. A task that is still working, or has results the model hasn't read, still keeps the session where it is until that clears.
Thanks @zackleman for reporting this and for the implementation plan in #5927. (#6260) -
eve now renders each model call's system prompt from the current deployment's agent files instead of storing it with the session.
Session checkpoints move to version 19, withoutagent.system. A deployment from before this change refuses to take over a session this one wrote, so the session stays on the deployment that wrote it, such as after a rollback. (#5638) -
Show the expected GitHub-side result as the gh tool's activity label instead of the generic tool name. (#5668)
-
Fix workflow hook ownership checks and preserve workflow error types and retry timing.
hook.getConflict()now returns the existing owner's run ID inside workflow bodies.FatalErrorandRetryableErrorcaught from steps retain their class identity, and workflow-createdRetryableErrorvalues honorretryAfter. (#5937) -
Allow dynamic schedules on Vercel preview and custom-environment deployments instead of rejecting operations outside production.
The default Vercel provider uses the deployment's OIDC credentials to access its own schedule track. Preview schedules remain separate from production schedules. (#5946) -
Answers eve discards, such as an empty answer it asks the model for again or a
content-filteranswer that fails the turn, now record their usage on the session stream and count toward session usage andlimits.sessionUsage, like a steered answer always has.
A reissued answer'susage.recordedfollows itsmodel.retried; a failed run's follows itsmodel.settled. Thanks @zackleman for reporting this in #5918. (#6253) -
A prompt that OpenAI refuses for possible cybersecurity (
cyber_policy) or biological (bio_policy) risk now fails only its turn instead of ending the session. (#5772) -
Start a fresh session when a channel message reaches a session whose Vercel deployment was deleted, instead of failing with
RunKeyFetchError.
Thanks @kashifrayani for diagnosing the channel failure in #5261. (#5954) -
Replace the vendored Turndown dependency with a small linear-time HTML-to-Markdown converter for web fetch and Microsoft Teams messages. (#6220)
-
Retry model calls that AI Gateway aborts with
gateway_stream_timeoutinstead of parking the session after the first cut stream.
Thanks @Benny-Gil for the original fix in #3108. (#4558) -
Model calls now retry when a stream chunk fails the provider's schema (
AI_TypeValidationError) or when AI Gateway's provider stream ends before the response finishes (gateway_stream_terminated).
Thanks @zackleman for reporting these in #5911 and #5912. (#6249) -
A root session whose
otel({ tracePolicy })withholds inputs or outputs, or drops the trace, no longer tags its workflow run as content-visible, so observability stops showing run data the policy excludes.
A trace policy can only hide content its audience would show by default. A private or unknown-audience run stays hidden even when its policy records content, because Agent Runs'exportPolicymay still redact those spans. Sessions without OpenTelemetry keep the audience default.
Thanks @zackleman for reporting the related visibility gap in #5931. (#6294) -
Only sign-ins the runtime starts can hold a turn.
A tool result shaped like a sign-in request, such as JSON from an MCP or OpenAPI connection, no longer opens a sign-in or changes who the turn runs as. (#5790) -
Fail closed for repository-based authorization policies when GitHub commands use a caller's unscoped token.
User-modeauthorizecallbacks always receiverepository: null, regardless of the command's declaration. Use GitHub App tokens with a fullowner/namedeclaration for repository allowlists. Policies that intentionally permit the caller's full GitHub access can continue to authorize throughauth. (#5903) -
Fix
eve devrequests that use a sandbox failing withENOENT … sandbox-preparation.lockwhen another request finished preparing sandboxes at the same time.
These requests now wait for the other request and continue, as they already did while preparation was in progress. (#6388) -
The experimental Vercel schedule provider bundles Schedules SDK 0.0.3, the first stable release after alpha.19. (#6027)
-
Fix delays and failures in server shutdown, session streams, successor sessions, and
eve devstartup, and start everyevecommand faster. (#6349)- A self-hosted eve server exits promptly after SIGTERM or SIGINT, including after it ran sessions.
session.stream()stops reading a session's events as soon as a channel stops iterating it.- A successor session starts its next turn at once when the run it moved from has already ended, instead of up to 10 s later.
eve devno longer fails requests that arrive during startup with aLoadCompiledManifestError.- Every
evecommand starts faster by loading the inspection code foreve remote info --urlonly when that command runs.
-
A turn's input now joins history before its first model call, so a model call that fails keeps the person's message for the next turn.
A response the provider filters is the exception: a refusal note replaces its turn's input, so the next turn doesn't send that input again. Completed tool calls and their results stay in history, so the model knows which actions already ran.
A compaction now opens only once it summarizes or rewrites the history, sosession.compact()records no change when its model doesn't resolve or the history has nothing to compact. (#5638) -
eve's session loop now runs as a kernel that owns every session transition, with no change in behavior. (#5638)
-
Report a sign-in the runtime cancelled (withdrawn, interrupted, or abandoned) as "sign-in cancelled" in Slack and other channels, instead of a red error with the internal reason code, such as
(turn-cancelled).
The GitHub sign-in's failure message now tells the person how to retry. (#5994) -
One answer now settles every parallel subagent waiting on the same Vercel Connect sign-in for the same person.
Signing in on any one of their sign-in cards completes every other subagent waiting on that grant, and declining one declines the others, so none of them asks again this turn. A sign-in callback with the provider'saccess_deniednow settles the sign-in as declined rather than as a retryable failure. A failed sign-in still settles only its own card. The parent calls each subagent's own callback, and each subagent settles it under its own principal, so no principal or credential passes between them. Sign-ins without a grant, for another principal, or minted by another deployment are still answered one by one. (#6086) -
Prevent
gh-signed-commitfrom publishing another file's contents for paths that resemble Git stage syntax or silently losing file modes and types.
The command now reads staged paths literally and rejects additions or updates involving executable files, symlinks, submodules, or mode changes before contacting GitHub. Staged changes remain intact; publish unsupported changes with native Git and a configured signing key. (#5863) -
Deliver Slack DM thread replies posted with "Also send to direct message" to the agent.
Thanks @dohooo for reporting this in #5774. (#5776) -
Slack no longer copies a direct-message question's answer into the shared thread: once the request settles, the thread's
Waiting on a responsenote says only who answered, while the DM card still shows the answer.
Approval notes still name the decision, such asAnswered: Approve. (#6041) -
Keep an answered ephemeral Slack card in its thread instead of also showing it at the top of the channel. (#6381)
-
Remove a Slack sign-in prompt when its Cancel button is clicked after the held turn has already ended, and log when Slack refuses to delete the prompt. (#5995)
-
Drop the redundant "Only you can see this message" from the Slack sign-in card; Slack already labels ephemeral messages "Only visible to you". (#6002)
-
Send a Slack sign-in prompt to the person's DM when the session has no thread, instead of posting a status top-level in the channel.
The DM names the channel the request came from, is edited in place with the outcome, and needs no Slack scope beyondchat:write. If the DM can't be sent, eve posts in the channel as before. Threaded sessions and code channels are unchanged. (#6007) -
Steering no longer discards a model call that is streaming a tool call's input, so the model doesn't write a long input twice.
The call finishes, the tool runs, and the new message applies at the next step boundary in the same turn.
Thanks @zackleman for reporting this and proposing the fix in #5929. (#6257) -
Ending a stranded session now writes the same checked commit as any other session end.
A stranded stream that never recordedsession.started, such as one an older deployment opened, gets it in the commit that ends the session. (#5638) -
Fixed subagent approvals answered from Slack, or with any
stateon the response, failing the subagent with "Session delivery has no identity" instead of running the approved call.
Thanks @Phelickz for reporting this in #5726. (#5728) -
Keep the head of a task result line that overflows the 50 KB budget instead of replacing it with
[truncated], so a one-line JSON result past the budget still reaches the model.
Thanks @nsxdavid for reporting this in #5746. (#5748) -
When
eve__task_waitreturns with one task's result while others are still working, the result now tells the model to wait again if its reply needs the rest, so it no longer sends a partial answer first. (#6380) -
eve__task_waitnow waits at most 30 minutes when a call omitstimeoutSeconds, so a task that never reports can't hold a turn open indefinitely. (#5300) -
AI SDK telemetry integrations no longer receive tool arguments, results, or raw errors for a call whose
recordInputsorrecordOutputssetting is off.
eve runs agent tools itself, so the AI SDK does not filter their telemetry events. eve now removes the excluded content before it calls each integration, the same way the AI SDK filters the events it sends. Integrations that ignore the per-call settings, such as Sentry's eve integration, previously recorded tool arguments for private conversations. (#6238) -
Make connection sign-ins countable in traces: each sign-in span names its agent, a failed sign-in records its reason, and a call a connection refused records which connection and why.
agent.approvalspans now carrygen_ai.agent.nameandagent.name, so a query scoped to one agent no longer drops its sign-in prompts. A sign-in that fails with a reason code such asaccess_deniedrecords it asagent.connection.authorization.reason; a sign-in that ends any other way, such as one a new message withdrew, records none. A tool call that fails withConnectionAuthorizationFailedError, including one that never asked anyone to sign in, such asprincipal_requiredorsign_in_unavailablein a turn a schedule started, recordseve.connection.nameandagent.connection.authorization.reasonon itsexecute_toolspan. Only reason codes are recorded: a free-text reason or error message stays off the span whatever the trace policy records. (#6078) -
Sessions recorded before eve 1.0 now read the way a current eve records them, and opening a subagent's stream through such a parent no longer re-reads the parent's whole history on every open and reconnect, which could make long sessions answer 404
descendant_unavailable.
eve now verifies the child against only the parent's stored line at the requested position, whichever eve version wrote it.
A question or approval that a subagent relayed before eve 1.0 now reads as a current relayed request: it names the task it came from when there is one, and carries the subagent's session, request, and the call it asks about. A relayed approval no longer reads as an approval of the parent's own subagent call.
Turns recorded before eve 1.0 now keep their trace context when read: each convertedturn.startedcarries thetraceits stored line recorded, as a turn a current eve runs does. A malformed recorded trace reads as absent instead of failing the line's schema.
Thanks @zackleman for reporting these in #5928, #5933, and #5934. (#6250) -
Vercel builds without
VERCEL_OIDC_TOKENno longer fail for agents whose sandbox templates have nothing to prepare, such as a freshly scaffolded agent with no sandbox, skills, or workspace files.
Templates with apreparecallback, managed workspace or skill files, or a Vercelsourcestill require the token. Builds without it fail with the instruction to runvercel linkandvercel pull. Unrelated provider preparation errors retain their original messages. (#6184) -
Fixed a session on
VercelSandboxfailing every turn after its stopped sandbox's snapshot expired. eve now starts a fresh sandbox for the session, as it does when the sandbox is gone.
Thanks @BilalAtique for reporting this in #4393 and @mahirhir for the reproduction. (#6182) -
Vercel sandboxes refresh or replace expired and near-expiry
VERCEL_OIDC_TOKENcredentials before template builds to avoid 403invalidTokenerrors.
WhenVERCEL_TEAM_ID(orVERCEL_ORG_ID) andVERCEL_PROJECT_IDwere set, eve usedVERCEL_OIDC_TOKENdirectly without checking its expiry, so a build that started after the token expired failed while preparing sandbox templates. eve now resolves the OIDC token through the Vercel OIDC helper, which attempts refresh within five minutes of expiry, and falls back toVERCEL_TOKENwhen it is set and the OIDC token can't be used. (#6188) -
Vercel sandboxes created without a snapshot now receive their configured network policy at creation, so an interrupted first open cannot leave them with unrestricted network access.
Base setup needs no network access. Reopening a sandbox preserves its live policy, including changes made throughsetNetworkPolicy(), rather than applying changed open options.
Existing sandboxes are not migrated or reset. Recycle any sandbox that may have been left unrestricted by an interrupted initialization before this fix. (#6042) -
Fix
eve/reactandeve/clientthrowingReferenceError: e is not definedin production builds from custom webpack setups older than 5.90. (#5042) -
Show workspace agents on the Vercel project overview card when
vercel.tscomposes them withwithEve.
withEvenow writes the root.eve/agent-summary.jsonindex that points Vercel at each member's summary, matching the hostlesseve buildpath. Thanks @cnaccio for reporting this in #5706. (#5710) -
defineWorkflowToolnow types the output thatendsTurnandtoModelOutputreceive the way eve produces it.
A generator body's output includes its return value, not only its yields. A tool with anoutputSchemagets that schema's output, as the definitiondefineWorkflowToolreturns already does. (#6430) -
Workflow and step modules can now embed files from
node_moduleswith relative asset imports.
Before,eve buildfailed withUNLOADABLE_DEPENDENCYfor an import such as../node_modules/pkg/README.md?raw, even though the same import worked in a tool. Thanks @mikestevenson-aries for reporting this in #5847. (#5849) -
Throw a clear, non-retrying error when a
defineState()handle is read or updated inside a workflow tool's"use step"function.
A step runs outside the session that owns the state, soget()silently returnedinitial()andupdate()silently discarded its write. Code that relied on that now fails the step without a retry. Return the value from the workflow tool and update state in acall.settledhook instead; see the State docs. (#6201) -
Self-hosted eve servers now close their Workflow world on shutdown, so a pending workflow
sleepor delivery retry no longer holds the process open until the supervisor kills it.
If closing the world fails or takes longer than 5 seconds, eve logs it and still runs the rest of its shutdown, including sandbox shutdown and the final trace flush. (#5879) -
eve build,eve dev, andeve evalnow build a workspace extension after the workspace extensions it depends on, so an extension whose subagent mounts another workspace extension builds from a clean checkout.
Thanks @dretanacr for reporting this in #5837 and for the implementation plan. (#5839)