Agent Configuration
An agent's optional agent.ts calls defineAgent (from eve) to configure the model and other runtime behavior. The root agent's file lives at agent/agent.ts, or in the app root with a flat layout. Declared subagents have their own agent.ts and accept the same configuration.
Set the model
A typical config selects a model:
For a static AI Gateway model ID, make the same change with
eve set model anthropic/claude-opus-5.5 from the project root or
/model anthropic/claude-opus-5.5 in the local dev TUI.
Omit the root agent.ts to use openai/gpt-6-luna-fast with reasoning: "high". When agent.ts is present, model is required.
Every local agent.ts, root or subagent, must export the value defineAgent returns, and so must a dynamic subagent resolver that selects a local agent. The build rejects a plain object with Export defineAgent({...}) from "<path>".
A gateway model ID string routes through the Vercel AI Gateway. To call a provider directly and configure the model in code, pass a model instance. eve types it as EveLanguageModel, exported from eve and eve/models, and every AI SDK language model satisfies it.
With a static Gateway model, agent.ts needs no code at runtime. A dynamic model or a model instance keeps agent.ts loaded at runtime, because eve resolves it while the agent runs. See Authored module lifecycle.
Use eve's helpers for direct OpenAI or Anthropic access without installing another provider package:
openai() from eve/models/openai defaults to gpt-6-luna-fast. Both helpers accept an optional native provider model ID and read OPENAI_API_KEY or ANTHROPIC_API_KEY. In local development they can also use credentials saved through /login; deployments need the API key in the server environment.
For a local ChatGPT subscription, use chatgpt() from eve/models/openai and sign in with /login. It defaults to gpt-6-luna-fast and can't run in a deployment.
/login can switch a static Gateway string to an eve helper and manage its import, and /model changes the selected model and settings immediately. Edit custom provider SDK calls and dynamic expressions by hand. For provider-specific configuration, install an AI SDK provider package and pass its language model.
Model use is subject to the terms, data-processing commitments, retention behavior, and available controls of the selected provider and routing path. Review the AI Gateway model catalog for gateway-routed models, and review the provider's terms when you configure a direct model instance.
eve fills some provider options by default. A value you set at the same path wins and is sent unchanged.
| Option | Calls | Default value |
|---|---|---|
providerOptions.openai.safetyIdentifier, providerOptions.anthropic.metadata.userId | OpenAI and Anthropic model and compaction calls | SHA-256 fingerprint of the turn's auth.current authenticator, issuer, type, id, and subject. Unset when auth.current is null. |
providerOptions.gateway.sessionId | AI Gateway calls | The Agent Runs gen_ai.conversation.id, shared by every turn, delegated subagent, and compaction call in the conversation. |
providerOptions.openai.promptCacheKey | Direct OpenAI and chatgpt() calls | SHA-256 hash of the session ID, unique per subagent session. |
The safety identifier never contains the caller's raw identity fields or attributes. It follows the current caller when a later turn changes users. AI Gateway hashes session IDs longer than 256 characters.
The Gateway session ID groups the conversation's generations into one session in
the AI Gateway logs Sessions view. It also drives
session affinity.
With affinity, AI Gateway first tries the provider that served the previous
call, so that provider can read the prompt from its cache. Affinity chooses only among the
providers your routing allows, but it can move one ahead of your order. To keep
order exactly, set sessionAffinity: false:
Use a local model
To test against a model on your own machine, use the AI SDK OpenAI-compatible provider. It works with any local server that implements the OpenAI Chat Completions API, such as Ollama, LM Studio, llama.cpp, or vLLM. With Ollama:
- Context window. AI Gateway has no metadata for local models, so set
modelContextWindowTokensto the context length your server allocates, not the model's maximum. eve uses it to decide when to compact. Ollama allocates as little as 4K tokens by default; raise it to at least 64K for agents, as above. - Tool calling. eve agents call tools on most turns, so pick a model with
native tool-calling support.
gpt-oss:20b,qwen3, andgemma4are good starting points on Ollama. - Usage.
includeUsage: truelets token usage reach eve's session limits. Local models report no cost, socostUsdstays unset in asessionUsagecheck. - Other servers. Change
baseURL, for example tohttp://localhost:1234/v1for LM Studio. PassapiKeyfor a remote OpenAI-compatible server that requires one.
A deployment cannot reach a server on your machine, so use a Gateway or hosted provider model when you deploy.
Choose the model dynamically
To select a model from the incoming prompt with an AI SDK decision model, use
auto from eve/models.
model also accepts defineDynamic(fn) from eve/models or eve. The function returns the
model, and a dynamic model has no compiled default.
The function returns a Gateway model ID, a model instance such as an AI SDK language model, or a selection object. See Dynamic capabilities for the context and memo rules.
- When it changes. eve runs the function before each ordinary model call. A memo keyed by
ctx.turn?.id ?? nullkeeps a choice for the turn;ctx.session.idkeeps it until a deployment change. Switching models can reduce prompt-cache reuse. - Failures stop the turn. A thrown error or invalid selection fails the turn before the
provider call.
nullis not a model. Missing credentials fail at request time. - Serialization. Only memo results must be JSON. The function can return a live provider
instance built from those results.
ctx.modelis unavailable during model selection. - Selection object.
{ model, reasoning?, modelContextWindowTokens?, modelOptions? }. OmitmodelContextWindowTokensto read it from the AI Gateway model catalog thateve buildoreve devrecorded, without a network request. A model that catalog doesn't list fails the turn. SetmodelContextWindowTokensfor an unlisted, custom, or newly published model, or rebuild. Dynamic agents cannot set siblingmodelContextWindowTokensormodelOptionsfields; return per-model values from the function.
The session.started runtime identity does not include a model ID for a dynamic agent. Each public
model.started event reports the concrete model selected for that model call.
Reasoning effort
reasoning sets the model's reasoning effort through AI SDK's provider-agnostic
option. In an authored agent.ts with a static model, omit reasoning to use
the provider's default.
Supported values are "provider-default", "none", "minimal", "low",
"medium", "high", and "xhigh". The selected model and provider determine
which levels are available and how they map to provider-native settings. Use
modelOptions.providerOptions for provider-specific reasoning controls.
A dynamic model selection can return reasoning to override the agent setting;
omit it to inherit the agent setting.
Run eve set model --reasoning high to update this field from the command line.
Prompt caching
eve caches prompts automatically for AI Gateway models and for Anthropic models
it recognizes by provider or model id. On a directly called model, set
modelOptions.promptCache to use a 1-hour cache. It also marks an unrecognized
model as Anthropic, such as a Bedrock application inference profile:
Not every Claude model supports a 1-hour cache. eve rejects promptCache on
Gateway models; use providerOptions.gateway.caching instead.
Compaction
Compaction summarizes older turns as the conversation approaches the context window, and is on by default. The token count includes the fixed checkpoint prompt, so compaction starts before the conversation alone reaches the threshold. Lower compaction.threshold, a fraction from 0 to 1, to compact sooner:
See Default harness for how the loop applies it.
Runtime limits
limits sets eve's runtime caps. sessionUsage receives the session's usage
and returns true when the session must stop starting model calls:
sessionTimeoutMs sets how long any session, including a delegated session,
may sit idle before eve completes it. Omit it for 30 days, or set it to false
to disable the timeout. The idle window starts when the session is created. It
restarts each time a turn ends, including turns that clear or compact the
context or are cancelled. A session never expires while a turn is open, such as while its
tasks work or it waits for a person to answer. Process restarts
don't change the window.
When the window elapses, eve emits session.ended with outcome: "completed"
and releases the channel addresses, such as a Slack thread, that route messages
to the session. The next message at that address starts a new session. To carry the earlier conversation over, pass it as
prior history. A session with
zero retention loses its stored payloads when it ends.
sessionUsage gets two TokenUsage records, a type exported from eve. total is everything the session has
spent, and window is what it spent since the last approved continuation. Each
record has these fields:
| Field | Meaning |
|---|---|
inputTokens | All input, including cache reads and writes. |
cacheReadTokens | History the provider replays from its prompt cache on every step. Subtract it from inputTokens to count only new input. |
cacheWriteTokens | Input written to the prompt cache. |
outputTokens | Generated output. |
costUsd | Model token cost in US dollars that AI Gateway reports with each step. Excludes tool and infrastructure spend. Unset when no step reported a cost. |
window is total minus the session's
total when its
own budget prompt was last accepted. Before the first approval, it equals
total. Accepting a budget prompt that a subagent passed up starts the
subagent's window, not the parent's. The window survives redeploys and
replays.
Omit sessionUsage to stop at 40_000_000 new input tokens per window:
sessionUsage can raise its threshold after each approval. This limit asks
at 20,000 new input tokens, then at 40,000, 80,000, and so on:
Set sessionUsage: false, or a callback that always returns false, to leave
sessions uncapped. eve calls a sessionUsage callback before each model call
once the window has usage. The model call that crosses a limit finishes, because
exact usage arrives after the call completes. Before the next model call, eve
pauses the turn (turn.paused) and sends a continuation prompt:
| Option | Result |
|---|---|
| Continue | Starts a new window and resumes the same turn. |
| Stop | Cancels the turn (turn.settled with outcome: "cancelled"), not an error. The session stays resumable, but because it is still over budget, the next message prompts again. |
Declining a delegated child's prompt cancels the root turn and the whole delegation tree, so the parent never receives an error result it could retry.
A message that answers neither option waits behind the open prompt. It starts
no second prompt or turn. After Continue, the paused turn receives it
(delivery.consumed).
If an earlier deployment showed the continuation prompt, that turn has already ended. A message that answers neither option waits behind the prompt and emits no event until Continue. Continue starts a new turn that receives the waiting message once.
Some sessions can't request input from a human, such as markdown schedules and
delegated runs without input proxying. They skip the prompt and fail the next
model call with SESSION_USAGE_LIMIT_REACHED. Its details carry the total and
window usage the check saw.
Each subagent session checks its own usage against its own sessionUsage, or
the root agent's when it authors none. A dynamic subagent always uses the root
agent's. Remote agents run under their own deployment's limits.
A child's usage, including its own subagents', also counts in the parent's
usage. Approving a continuation starts a new window without erasing total.
The parent counts delegated usage at these points:
| Delegated work | Counts against the parent |
|---|---|
| Agent task | With each reply. A turn with no reply, such as a cancelled one, counts with the next reply, or when the turn ends if no call waits. |
ctx.agent session from any other serve workflow tool | The same way as an agent task. |
ctx.agent session from an execute or task tool | When the tool finishes. |
| Remote agent | The same way as an agent task, cost included. |
Some delegated usage doesn't count against the parent:
- A
ctx.agentturn still running when its workflow tool finishes or is cancelled. - The
ctx.agentusage of anexecutetool whose parent turn is cancelled while it waits. - What a cancelled agent task's own subagents spend after the task reports its cancelled turn.
A cancelled agent task ends and sends no further reply. Usage the cancelled run reported up to that point still counts against the parent when its usage report or final outcome arrives.
Workflow world
The Workflow world is the backend that stores and runs sessions, so they survive restarts and redeploys. Omit
experimental.workflow.world to use Vercel Workflow on Vercel and the SDK's
local world in local development or eve start. Self-hosted deployments can
select a world package in the root agent.ts:
Install the package in your app; it must export a default factory or a
createWorld() function. Install a version built against the same
@workflow/* major version as your eve release, currently 5.x:
eve fails at startup, naming the version to install, when the world targets a different major version.
Put credentials, such as the Postgres connection string, and host-specific
options in the environment variables the world package reads, not in
agent.ts. If the package must stay external in hosted output, list it in
build.externalDependencies. See Workflow worlds
to choose a world and set up the Postgres world's database.
Workflow checkpoint batching
eve saves a Workflow step after every model call and its inline tool calls. experimental.workflow.modelCallsPerStep lets one step run several
sequential model calls:
The value is a positive-integer maximum. Omit it for 1. It applies
separately to each root agent or declared subagent. A higher value can reduce
save overhead in sequential tool loops, but more work runs again after a crash.
If the step is interrupted, its earlier model calls and inline tool calls can
run again, repeating provider costs, events, and side effects. Use stable
idempotency keys for non-idempotent tools.
A batch ends before eve waits for input, authorization, or other blocking work. It can end below the maximum when the turn completes or steering arrives. Before assistant output begins, steering can interrupt pending model generation; running tools finish before the batch yields. This option is experimental and may change or disappear in any release. See Execution model and durability for the retry behavior.
Run data retention
Run-data retention is how long the Workflow World keeps a session's run data.
Omit experimental.workflow.retention to derive it from the session's resolved
OpenTelemetry trace policy when
the session starts:
- When the policy allows both inputs and outputs, eve uses the World's default retention period.
- When the policy drops the trace or excludes either content direction, eve
requests deletion when the run ends (Workflow's
experimental_retention: 0). Workflow can't delete inputs and outputs separately.
Without a custom policy, public conversations and development sessions use the
World's default. Private and unknown-audience sessions outside development
request 0, even with no OpenTelemetry destination installed. Destination
export filters and lifecycle-provider policies don't change the decision.
Set experimental.workflow.retention to 0 to always request deletion, or to
"default" to always keep run data for the World's default period. This
override is experimental and has no compatibility promise:
The resolved value applies to every run of the session, including runs after a redeploy. Session timeout and workflow tool runs keep the World's default.
Retention applies per agent. A subagent with its own session uses
its own explicit value or derives retention from its resolved trace decision,
including any inherited content ceiling. experimental.workflow.world is root-only.
At 0, supporting Worlds delete run and step inputs, outputs, and errors;
event payloads; and stream contents when the run reaches a terminal state. The
data remains available while the session is active. Run, step, and event records
remain for the World's default period. These records include IDs, timestamps,
statuses, step names, and attributes, which can contain content such as eve's
session title. Local traces, exported telemetry, and data stored by tools, channels, or
model providers are not deleted.
The Workflow World enforces deletion. A World older than spec version 4 rejects
0, and a spec version 4 World without retention support keeps the data.
Confirm support with your World provider. See
Workflow data retention.
⚠️ At
0, completed session transcripts become unreadable. Deletion races reads of finished runs. Depending on the World, reading deleted session history returns either an empty stream or410withcode: "session_expired". Persist anything you need to keep from inside a tool, or setretention: "default"to preserve completed-session reads independently of tracing.
Other defineAgent fields
All other defineAgent fields are optional. For the exported types, see the TypeScript API Reference.
| Field | Type | Default | Description |
|---|---|---|---|
reasoning | AgentReasoningDefinition | provider default | Provider-agnostic reasoning effort forwarded to the agent's turn model calls. |
modelOptions | AgentModelOptionsDefinition | none | Provider option overrides forwarded to the model call, and promptCache settings. |
limits | AgentLimitsDefinition | field-specific | eve's runtime limits. |
experimental | AgentExperimentalDefinition | unset | Unstable opt-ins: workflow.world, workflow.modelCallsPerStep, and workflow.retention. |
build | { externalDependencies?: string[] } | none | Hosted-build packaging controls. externalDependencies keeps listed packages unbundled and includes them in the hosted output. |
tool | boolean | "deferred" | true | Exposes this agent to its parent model as a tool. "deferred" hides it from the tool list until the model finds it with eve__search and calls it with eve__tool. On the root agent, controls the built-in agent tool. With false, authored workflow tools can still call a subagent through ctx.agent(). |
externalDependencies only controls packaging; it doesn't authorize, configure, or review any third-party service those packages call.
During eve dev, packages listed in externalDependencies use normal Node.js resolution instead of being bundled, so restart the dev server after replacing one.
Where adjacent settings live
| Concern | Lives in |
|---|---|
| Instructions prompt | agent/instructions.md, Instructions |
| Per-tool approval (HITL) | agent/tools/*.ts, Tools |
| Inbound auth & network policy | the channel layer, Auth & route protection |
| Sandbox / workspace | agent/sandbox/, Sandbox |
| Telemetry & debugging | agent/instrumentation/, Instrumentation |
What to read next
- Default harness for compaction and model context, and Built-in tools for the framework-provided tool set
- TypeScript API Reference for every
defineAgentfield and type - Subagents for the
descriptionrequirement and child-agent config