mirror of
https://github.com/vercel/eve.git
synced 2026-09-20 05:35:39 +08:00
docs: add legal safety guidance (#10)
This commit is contained in:
@@ -33,6 +33,20 @@ You author an agent as a directory on disk. The directory is the contract:
|
||||
|
||||
The framework package is `eve`. The CLI binary is `eve`.
|
||||
|
||||
## Preview Terms and Safeguards
|
||||
|
||||
Eve is currently a preview and subject to the Vercel beta terms; the framework, APIs, documentation, and behavior may change before general availability.
|
||||
|
||||
As the deployer, it is your responsibility to ensure your agent complies with applicable laws.
|
||||
|
||||
You are responsible for configuring approval policies, tool restrictions, connection scopes, route/session authorization, sandbox controls, telemetry exports, and other safeguards appropriate for your use case.
|
||||
|
||||
Before using Eve with non-public, sensitive, regulated, or production data, review which default tools, custom tools, MCP tools, shell/file/web tools, connected services, subagents, schedules, and external actions are available to the agent.
|
||||
|
||||
Require human approval or other safeguards for sensitive, irreversible, regulated, financial, healthcare, employment, housing, legal, safety-impacting, user-impacting, or external side-effecting actions.
|
||||
|
||||
Unless you configure stricter controls, Eve agents may operate with permissive settings, including tool execution without human approval where approval is omitted and sandbox network egress that is not deny-all. Do not rely on model behavior alone to prevent sensitive or irreversible actions.
|
||||
|
||||
## What Eve Prioritizes
|
||||
|
||||
- Markdown-first authoring for instructions and procedures
|
||||
|
||||
@@ -10,6 +10,7 @@ const title = "Eve";
|
||||
const tagline = "Like Next.js for web apps, but for agents.";
|
||||
const description =
|
||||
"Markdown for instructions and skills, TypeScript for tools. Durable by default.";
|
||||
const betaAgreementHref = "https://vercel.com/docs/release-phases/public-beta-agreement";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title,
|
||||
@@ -17,9 +18,15 @@ export const metadata: Metadata = {
|
||||
};
|
||||
|
||||
const HomePage = () => (
|
||||
<div className="mx-auto w-full max-w-[1080px] pb-32 [&_h1]:tracking-tighter [&_h2]:tracking-tighter [&_h3]:tracking-tighter">
|
||||
<div className="mx-auto w-full max-w-[1080px] pb-32">
|
||||
<section className="relative flex flex-col items-center px-4 pb-32 pt-32 text-center sm:px-12">
|
||||
<h1 className="max-w-3xl text-5xl font-bold tracking-tighter text-gray-1000 sm:text-6xl xl:text-7xl">
|
||||
<Link
|
||||
href={betaAgreementHref}
|
||||
className="mb-6 rounded-full border border-amber-300 px-3 py-1 font-medium text-amber-700 text-xs transition-colors hover:bg-amber-50"
|
||||
>
|
||||
Public preview
|
||||
</Link>
|
||||
<h1 className="max-w-3xl text-5xl font-bold text-gray-1000 sm:text-6xl xl:text-7xl">
|
||||
The Framework
|
||||
<br />
|
||||
for Building Agents
|
||||
|
||||
@@ -15,6 +15,19 @@ export const DocsLayout = ({ tree, children }: DocsLayoutProps) => (
|
||||
}}
|
||||
tree={tree}
|
||||
>
|
||||
<aside className="mx-auto w-full max-w-[900px] px-4 pt-6 md:px-6 md:pt-8 xl:px-8 xl:pt-10 [grid-column:main]">
|
||||
<div className="border-amber-600 border-l pl-4 text-gray-900 text-sm leading-6">
|
||||
<span className="font-medium text-gray-1000">Public preview.</span> Eve is currently a
|
||||
preview and subject to the{" "}
|
||||
<a
|
||||
className="font-medium text-gray-1000 underline decoration-gray-600/40 underline-offset-4 transition-colors hover:decoration-gray-1000"
|
||||
href="https://vercel.com/docs/release-phases/public-beta-agreement"
|
||||
>
|
||||
Vercel beta terms
|
||||
</a>
|
||||
; the framework, APIs, documentation, and behavior may change before general availability.
|
||||
</div>
|
||||
</aside>
|
||||
{children}
|
||||
</PackageDocsLayout>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
export const Logo = () => (
|
||||
<span className="font-semibold text-gray-1000 text-lg leading-none tracking-[-3%]">Eve</span>
|
||||
<span className="flex items-center gap-2">
|
||||
<span className="font-semibold text-gray-1000 text-lg leading-none">Eve</span>
|
||||
<span className="rounded-full border border-amber-300 px-2 py-0.5 font-medium text-amber-700 text-xs leading-none">
|
||||
Public preview
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
|
||||
export const github = {
|
||||
|
||||
@@ -17,6 +17,7 @@ import { cn } from "@/lib/utils";
|
||||
import { AgentMessage } from "./agent-message";
|
||||
|
||||
const AGENT_NAME = "eve-agent";
|
||||
const BETA_TERMS_HREF = "https://vercel.com/docs/release-phases/public-beta-agreement";
|
||||
|
||||
type AgentStatus = ReturnType<typeof useEveAgent>["status"];
|
||||
|
||||
@@ -42,9 +43,19 @@ export function AgentChat() {
|
||||
return (
|
||||
<main className="flex h-dvh flex-col overflow-hidden bg-background text-foreground">
|
||||
{isEmpty ? null : (
|
||||
<header className="flex h-14 shrink-0 items-center justify-center gap-2 pl-4 pr-2">
|
||||
<span className="text-muted-foreground text-sm">{AGENT_NAME}</span>
|
||||
<StatusDot status={agent.status} />
|
||||
<header className="flex h-14 shrink-0 items-center justify-center gap-3 pl-4 pr-2">
|
||||
<span className="flex min-w-0 items-center gap-2">
|
||||
<span className="truncate text-muted-foreground text-sm">{AGENT_NAME}</span>
|
||||
<StatusDot status={agent.status} />
|
||||
</span>
|
||||
<a
|
||||
className="rounded-full border border-amber-500/30 px-2 py-0.5 font-medium text-amber-700 text-xs transition-colors hover:bg-amber-500/10 dark:text-amber-300"
|
||||
href={BETA_TERMS_HREF}
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Public preview
|
||||
</a>
|
||||
</header>
|
||||
)}
|
||||
|
||||
@@ -87,7 +98,19 @@ export function AgentChat() {
|
||||
: "max-w-3xl shrink-0 pb-6",
|
||||
)}
|
||||
>
|
||||
{isEmpty ? <h1 className="font-medium text-5xl tracking-tighter">{AGENT_NAME}</h1> : null}
|
||||
{isEmpty ? (
|
||||
<div className="flex flex-col items-center gap-3 text-center">
|
||||
<h1 className="font-medium text-5xl tracking-tighter">{AGENT_NAME}</h1>
|
||||
<a
|
||||
className="rounded-full border border-amber-500/30 px-2 py-0.5 font-medium text-amber-700 text-xs transition-colors hover:bg-amber-500/10 dark:text-amber-300"
|
||||
href={BETA_TERMS_HREF}
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Public preview
|
||||
</a>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="w-full">{composer}</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
@@ -10,6 +10,20 @@ Important naming note:
|
||||
- The current published package name is `eve`.
|
||||
- The CLI binary is `eve`.
|
||||
|
||||
## Legal and safeguards
|
||||
|
||||
Eve is currently a preview and subject to the Vercel beta terms; the framework, APIs, documentation, and behavior may change before general availability.
|
||||
|
||||
As the deployer, it is your responsibility to ensure your agent complies with applicable laws.
|
||||
|
||||
You are responsible for configuring approval policies, tool restrictions, connection scopes, route/session authorization, sandbox controls, telemetry exports, and other safeguards appropriate for your use case.
|
||||
|
||||
Before using Eve with non-public, sensitive, regulated, or production data, review which default tools, custom tools, MCP tools, shell/file/web tools, connected services, subagents, schedules, and external actions are available to the agent.
|
||||
|
||||
Require human approval or other safeguards for sensitive, irreversible, regulated, financial, healthcare, employment, housing, legal, safety-impacting, user-impacting, or external side-effecting actions.
|
||||
|
||||
Unless you configure stricter controls, Eve agents may operate with permissive settings, including tool execution without human approval where approval is omitted and sandbox network egress that is not deny-all. Do not rely on model behavior alone to prevent sensitive or irreversible actions.
|
||||
|
||||
Casing convention:
|
||||
|
||||
- Use Title Case for page `title` frontmatter and `meta.json` section titles (Fumadocs renders the page `title` as both the sidebar entry and the `<h1>`, so one casing covers both) — e.g. `Execution Model & Durability`, `Dynamic Capabilities`, `Build an Agent`.
|
||||
|
||||
@@ -31,6 +31,8 @@ export default defineAgent({
|
||||
});
|
||||
```
|
||||
|
||||
Model use is subject to the terms, data-processing commitments, retention behavior, and available controls of the selected provider and routing path. Review the [AI Gateway model catalog](https://vercel.com/ai-gateway/models) for gateway-routed models, and review the provider's terms when you configure a direct `LanguageModel`.
|
||||
|
||||
## Compaction
|
||||
|
||||
Compaction summarizes older turns as you approach the context window. It's on by default, so you only tune when it kicks in. Lower `thresholdPercent` to compact sooner:
|
||||
@@ -57,6 +59,10 @@ See [Default harness](./concepts/default-harness#compaction) for how the loop ap
|
||||
| `outputSchema` | Standard Schema or a JSON Schema object | none | Structured return type for task-mode runs (a subagent, schedule, or remote job). Interactive conversation turns ignore it unless the client supplies a per-message schema. |
|
||||
| `build` | `{ externalDependencies?: string[] }` | none | Hosted-build packaging controls. `externalDependencies` keeps listed packages external while Eve compiles authored modules such as tools and channels, and traces those packages into the hosted output. |
|
||||
|
||||
`codeMode` is experimental and may change or be removed.
|
||||
|
||||
`externalDependencies` is a packaging control only. It keeps selected packages as runtime dependencies in the hosted output; it does not authorize, configure, or review any third-party service those packages may call.
|
||||
|
||||
## Where adjacent settings live
|
||||
|
||||
| Concern | Lives in |
|
||||
|
||||
@@ -11,6 +11,8 @@ A channel is the edge adapter between a platform and your agent. It does three t
|
||||
|
||||
Eve ships a base HTTP channel plus first-class platform channels, and you can author your own. Browse the full set in the [Integrations](/integrations) gallery.
|
||||
|
||||
Each channel has its own provider terms, data flow, auth model, and user-consent expectations. Before sending non-public, sensitive, regulated, or production data through a channel, confirm that the channel provider and your configured scopes, signature checks, route auth, and delivery behavior are appropriate for your use case.
|
||||
|
||||
## Where channels live
|
||||
|
||||
Channel files live under `agent/channels/` in the root agent. The file stem is the channel id: `agent/channels/intake.ts` is addressed as `intake`. Export the channel as the module's default export. Local subagents do not declare channels.
|
||||
@@ -55,6 +57,12 @@ Eve does **not** use the Chat SDK's runtime. The `Chat`, `Adapter`, and `Thread`
|
||||
| Linear issue delegation and Agent Sessions | [Linear](./linear) |
|
||||
| Anything else (internal webhook, WebSocket) | Custom channel (`defineChannel`, above) |
|
||||
|
||||
## Disclaimer
|
||||
|
||||
As the deployer, it is your responsibility to ensure your agent complies with applicable laws.
|
||||
|
||||
Where an Eve agent communicates with people, you may be required to disclose that they are interacting with an automated AI system where law requires it. Eve does not add this disclosure automatically; configure it in your instructions and/or channel responses.
|
||||
|
||||
## What to read next
|
||||
|
||||
- [Slack](./slack): the most common platform channel, end to end
|
||||
|
||||
@@ -72,6 +72,12 @@ Start a session without an inbound message through `receive(twilio, { message, t
|
||||
|
||||
Inbound media attachments are not supported on this channel today.
|
||||
|
||||
## Disclaimer
|
||||
|
||||
As the deployer, it is your responsibility to ensure your agent complies with applicable laws.
|
||||
|
||||
For example, you may be required to inform callers and texters that calls are recorded/transcribed and processed by an automated AI system, and obtain consent where required (including two-party-consent jurisdictions). For outbound SMS or calls you initiate, you may be required to get prior express consent, honor STOP/opt-out and quiet-hour rules, and complete required carrier registration.
|
||||
|
||||
## What to read next
|
||||
|
||||
- [Channels overview](./overview): the channel contract and every built-in channel
|
||||
|
||||
@@ -46,6 +46,8 @@ Notes:
|
||||
- **`connection_search`** is the model-facing `connection__search` tool. A search surfaces a connection's tools by their qualified name (e.g. `connection__linear__list_issues`), and the model can then call them directly. It's registered only when the agent has connections.
|
||||
- **`web_search`** has no local executor; the provider runs it. To supply your own implementation, override it with `defineTool()`.
|
||||
|
||||
Review these built-in tools before production use. Disable, wrap, restrict, or require approval for any tool that can access the filesystem, network, shell, or sensitive data.
|
||||
|
||||
## Override a default
|
||||
|
||||
Author a tool at the same slug and it takes over the built-in of that name. The file `agent/tools/write_file.ts` replaces the built-in `write_file` by existing:
|
||||
|
||||
@@ -20,6 +20,30 @@ The sandbox is the isolated side. The model runs shell commands there through th
|
||||
|
||||
A concrete trace makes the boundary clear. When the model calls a custom `charge_card` tool, its `execute` runs in the app runtime, reads `process.env.STRIPE_KEY`, calls Stripe, and returns `{ ok: true }`. The model sees only `{ ok: true }`: the key never leaves the app runtime, and nothing about the call touches the sandbox. The built-in `write_file` is the mirror image, running in the app runtime and proxying the write into the sandbox `/workspace`. Either way the model drives the work through tool calls and their results, never by holding a credential or reaching the runtime directly.
|
||||
|
||||
## Data flow at a glance
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
User["User or channel provider"] --> Channel["Channel route and route auth"]
|
||||
Channel --> Runtime["Eve app runtime and durable session"]
|
||||
Runtime --> Model["Configured model provider or Vercel AI Gateway"]
|
||||
Runtime --> Tools["Authored tools and connections"]
|
||||
Tools --> Services["Customer-selected external services"]
|
||||
Runtime --> Sandbox["Per-session sandbox"]
|
||||
Sandbox --> Egress["Allowed sandbox network egress"]
|
||||
Runtime --> Telemetry["Configured telemetry or eval provider"]
|
||||
```
|
||||
|
||||
Eve sends data where your agent configuration and runtime choices send it:
|
||||
|
||||
- Inbound channel data flows through the channel provider you configure, then into the Eve app runtime.
|
||||
- Model inputs and outputs flow to the model or routing path selected in `agent.ts`, such as a Vercel AI Gateway model id or a provider-authored `LanguageModel`.
|
||||
- Tool and connection calls flow to the external services, MCP servers, OpenAPI endpoints, and channels you configure.
|
||||
- Sandbox commands can reach network destinations allowed by the sandbox network policy.
|
||||
- Telemetry and eval data flows to the exporters and providers you configure in `instrumentation.ts` or eval settings.
|
||||
|
||||
Eve stores durable session and workflow state needed to resume conversations, stream events, replay completed steps, and show run observability. You are responsible for deciding whether the selected channels, model providers, connected services, sandbox egress destinations, telemetry exporters, retention settings, and deletion controls are appropriate for your data and use case.
|
||||
|
||||
## Credential brokering
|
||||
|
||||
Credential brokering gives the model _authenticated_ network access from inside the sandbox, like a `git clone` of a private repo or an authenticated `curl`, when there's no [tool](../tools) or [connection](../connections) to route it through. On the Vercel Sandbox backend, auth headers get injected at the sandbox's network firewall for matching domains. The secret stays in the app runtime; the sandbox process only ever sees the response. See [Vercel Sandbox Credential Brokering](https://vercel.com/docs/sandbox/concepts/firewall#credentials-brokering) for the platform mechanism, and [Sandbox](../sandbox) for the Eve policy API.
|
||||
|
||||
@@ -64,6 +64,8 @@ The stream is newline-delimited JSON (NDJSON), one event per line:
|
||||
|
||||
`reasoning.appended` and `message.appended` stream deltas as they arrive, and each one carries both the new delta and the cumulative text for the current block. The finalized block shows up on `message.completed` and `reasoning.completed`, which is the compatibility path for clients that don't render incremental streaming.
|
||||
|
||||
Note: consider the privacy, confidentiality, and user-experience implications for displaying, storing, or transmitting reasoning events in your application.
|
||||
|
||||
`message.completed` can fire more than once in a turn: the agent often emits interim assistant text before a tool call. To tell tool-call narration from a terminal reply, check `message.completed.data.finishReason`. `step.completed.data.finishReason` mirrors the step outcome, and usage lives on `step.completed`.
|
||||
|
||||
A delegated subagent publishes progress on its own child-session stream. The parent only emits `subagent.called` with a `childSessionId`, which a client uses to attach.
|
||||
|
||||
@@ -44,6 +44,8 @@ export default defineMcpClientConnection({
|
||||
});
|
||||
```
|
||||
|
||||
We recommend using no-auth connections only for services that are intentionally public, local-only, or otherwise protected outside Eve. Do not use no-auth connections for sensitive third-party services.
|
||||
|
||||
### Headers
|
||||
|
||||
Use `headers` when the server wants a non-Bearer scheme (an API-key header) or extra configuration. Headers stack on top of `auth`:
|
||||
@@ -86,6 +88,8 @@ export default defineMcpClientConnection({
|
||||
|
||||
`never()` lets every call through, `once()` asks for approval the first time in a session, and `always()` asks every time. The pause and resume is the same human-in-the-loop flow covered in [Tools](./tools).
|
||||
|
||||
For connection tools that can create, modify, delete, transmit, purchase, message, or access sensitive data, use approval, tool allow-lists, or other safeguards appropriate to the action.
|
||||
|
||||
## OpenAPI connections
|
||||
|
||||
`defineOpenAPIConnection` turns any OpenAPI 3.x document into connection tools, one per operation. Pass an HTTPS URL Eve fetches at runtime, or an inline parsed object:
|
||||
|
||||
@@ -5,6 +5,8 @@ description: "Ship eval results to Braintrust experiments or JUnit XML. Eve runs
|
||||
|
||||
Eve runs and grades everything itself; reporters ship the results out. The CLI prints a console summary by default (one line per eval, with failed assertions and their messages), and reporters from `eve/evals/reporters` add destinations on top.
|
||||
|
||||
You are responsible for ensuring any observability or eval provider is approved for the data exported to it.
|
||||
|
||||
Reporters attach in two places. Declare them in `evals.config.ts` to observe **every** eval in the run, the usual choice for a shared destination like one Braintrust experiment, so you don't repeat the reporter in each file. Or list them on an individual eval's `reporters` to scope a destination to that eval (or to a group of evals that share one instance).
|
||||
|
||||
## Braintrust
|
||||
|
||||
@@ -5,6 +5,8 @@ description: "Install Eve, scaffold your first agent, give it a tool, and run it
|
||||
|
||||
Eve is a filesystem-first framework for durable agents. You write capabilities under `agent/`, and Eve runs the model loop, persists every session, and serves the agent over HTTP and platform channels. You'll scaffold an app, add a tool, run it locally, then create, stream, and continue a session over HTTP.
|
||||
|
||||
Eve is currently in beta and subject to the [Vercel beta terms](https://vercel.com/docs/release-phases/public-beta-agreement). The framework, APIs, documentation, and behavior may change before general availability.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node 24 or newer
|
||||
@@ -16,6 +18,8 @@ The scaffold's default model is `anthropic/claude-sonnet-4.6`, which routes thro
|
||||
- A gateway model id needs `AI_GATEWAY_API_KEY`, or a `VERCEL_OIDC_TOKEN` pulled with `vercel link`.
|
||||
- A direct provider id needs that provider's key, derived from the model prefix. For example, `anthropic/claude-...` needs `ANTHROPIC_API_KEY`.
|
||||
|
||||
You are responsible for selecting a model, provider, and channel appropriate for your data and use case, and for complying with each provider's terms (as listed per model) and data-processing requirements.
|
||||
|
||||
If you skip this, the dev TUI flags the missing credential and its `/model` command walks you through pasting a key or linking a project.
|
||||
|
||||
## Quick start
|
||||
@@ -76,6 +80,8 @@ export default defineAgent({
|
||||
});
|
||||
```
|
||||
|
||||
Before using real customer data, confirm the selected model provider's terms, routing path, and retention settings are appropriate for that data.
|
||||
|
||||
Even at this size the agent can already do real work. The default harness gives it file, shell, web, and delegation tools out of the box. See [Default harness](./concepts/default-harness) for the full set and how to override or disable any of them.
|
||||
|
||||
### Add your first tool
|
||||
@@ -156,6 +162,8 @@ The stream is NDJSON, served as `application/x-ndjson; charset=utf-8`. For this
|
||||
|
||||
`reasoning.appended` and `message.appended` are optional live-streaming events. Clients that can't surface incremental output can ignore them and rely on `reasoning.completed` and `message.completed`.
|
||||
|
||||
Note: consider the privacy, confidentiality, and user-experience implications for displaying, storing, or transmitting reasoning events in your application.
|
||||
|
||||
The full set covers more lifecycle, human-in-the-loop, and authorization events, including `input.requested`, `turn.failed`, `authorization.required`, and `authorization.completed`. See [Sessions, runs and streaming](./concepts/sessions-runs-and-streaming) for every event and its data shape.
|
||||
|
||||
## Send a follow-up message
|
||||
|
||||
@@ -18,6 +18,8 @@ The route-auth policy lives on the HTTP channel factory (`agent/channels/eve.ts`
|
||||
- `POST /eve/v1/session/:sessionId`
|
||||
- `GET /eve/v1/session/:sessionId/stream`
|
||||
|
||||
These routes are protected by the channel's auth policy. Eve fails closed by default: production browser traffic is rejected unless you configure an authenticator that accepts it, and anonymous access requires an explicit `none()`.
|
||||
|
||||
`GET /eve/v1/health` is always public and skips the walk entirely, so load balancers and uptime monitors can probe it without credentials.
|
||||
|
||||
```ts title="agent/channels/eve.ts"
|
||||
@@ -92,6 +94,8 @@ Any other thrown error follows the normal channel failure path. When building a
|
||||
| `jwtEcdsa(...)` | You verify asymmetric JWTs minted by another system. |
|
||||
| `oidc(...)` | You want Eve to verify OIDC-issued tokens from an arbitrary issuer. |
|
||||
|
||||
Exercise caution for agents that process non-public, sensitive, regulated, or production data unless you have implemented other access controls.
|
||||
|
||||
### `localDev()`
|
||||
|
||||
Authenticates a synthetic `local-dev` principal, but only when the inbound request is addressed to a loopback hostname (`localhost`, `*.localhost`, `127.0.0.0/8`, or `::1`). The check keys off the request URL's hostname rather than the bare `process.env.VERCEL` flag, and that's deliberate: a deployment outside Vercel leaves `VERCEL` unset, so sniffing that flag alone would wave through all public traffic. There's one process-level exception. `vercel dev`, detected by `VERCEL=1` and `VERCEL_ENV=development` together, opens the local dev server even when it serves over a non-loopback host. Every other non-loopback request returns `null` and falls through.
|
||||
@@ -210,6 +214,8 @@ Inside runtime code, `ctx.session.auth` carries the result of the channel's rout
|
||||
|
||||
Use the principal on `auth.current` (or `auth.initiator`) to scope tools, resolve [dynamic capabilities](./dynamic-capabilities) per principal, or enforce tenant boundaries. There's no second per-session ownership ACL stacked on top of route auth. Access is decided at the HTTP boundary, and the durable session carries the caller snapshot forward into your runtime code.
|
||||
|
||||
Route auth does not enforce session ownership. If multiple users or tenants can reach the same route, you must implement the per-user, per-tenant, or per-session authorization your application requires.
|
||||
|
||||
## Tool and connection auth
|
||||
|
||||
Tool and connection auth is how your agent reaches an external service that wants an interactive sign-in, like an OAuth MCP server. Both a connection and an individual tool can declare an `auth` strategy; Eve drives the sign-in, caches the token per step, and re-runs the call once the caller authorizes.
|
||||
|
||||
@@ -67,6 +67,8 @@ That is an allowlist, not a denylist. The sandbox cannot read files, open a sock
|
||||
|
||||
[Code mode](../agent-config#other-defineagent-fields) is the broader version, where the model drives _all_ of an agent's tools (files, shell, web, and agents) from JavaScript. A workflow covers only the subagents. The two do not interfere. Enabling the `Workflow` tool leaves code mode untouched, and an agent can run both at once.
|
||||
|
||||
`codeMode` is experimental and may change or be removed.
|
||||
|
||||
## What to read next
|
||||
|
||||
- Declare the subagents a workflow orchestrates → [Subagents](../subagents)
|
||||
|
||||
@@ -5,6 +5,8 @@ description: "Trace an agent with OpenTelemetry in instrumentation.ts, read the
|
||||
|
||||
`instrumentation.ts` is where you configure how an Eve agent is observed. The framework auto-discovers `agent/instrumentation.ts` and runs it at server startup before any agent code. Its presence implicitly enables telemetry, so there is no separate `isEnabled` toggle.
|
||||
|
||||
If you intend to export telemetry, review the exporter destination, data categories, and required legal approvals before enabling telemetry.
|
||||
|
||||
## Three observability surfaces
|
||||
|
||||
Eve observes an agent through three distinct surfaces. They do not all live in this file, and they write to different places:
|
||||
@@ -50,6 +52,10 @@ Three more fields control what the AI SDK records inside those spans (see the AI
|
||||
- `recordOutputs` records model outputs on spans (defaults to `true`). Set it to `false` to disable output recording.
|
||||
- `functionId` overrides the function name on spans (defaults to the agent name).
|
||||
|
||||
For sensitive, regulated, or production data, set `recordInputs` and `recordOutputs` to `false` unless you have reviewed the exporter and its data-retention path.
|
||||
|
||||
You are responsible for ensuring any observability or eval provider is approved for the data exported to it.
|
||||
|
||||
The third configurable surface, [runtime context events](#runtime-context), attaches per-model-call values to these spans.
|
||||
|
||||
## Runtime context
|
||||
@@ -134,6 +140,8 @@ Tag writes are best-effort: a failure is logged once per process and then swallo
|
||||
|
||||
These tags power the **Agent Runs** tab in the Vercel dashboard. When you deploy on Vercel, the platform auto-detects `eve` as the framework and surfaces an Agent Runs view under your project's **Observability** tab, where you can browse sessions and drill into each conversation's trace, with no `instrumentation.ts` required. The tab is currently gated per team. See [Deployment](./deployment#view-runs-in-the-dashboard) for enablement. Agent Runs is separate from the OpenTelemetry export above. Use OTel when you want spans in Braintrust, Datadog, or another third-party backend.
|
||||
|
||||
Note: By default, telemetry records full message history and model outputs You may need to disclose these data flows in your privacy materials if utilized.
|
||||
|
||||
## Debugging
|
||||
|
||||
`eve info` is the fastest way to see what Eve actually picked up: the active tools, skills, subagents, schedules, routes, and discovery diagnostics. Eve also writes inspectable artifacts under `.eve/`, kept even when discovery hits errors:
|
||||
|
||||
@@ -53,6 +53,12 @@ Instructions never run code. When you need typed executable behavior, reach for
|
||||
|
||||
To resolve the prompt at runtime from session context (auth, tenant, or channel), wrap `defineInstructions` in a `defineDynamic` resolver. See [Dynamic capabilities](./guides/dynamic-capabilities).
|
||||
|
||||
## Disclaimer
|
||||
|
||||
As the deployer, it is your responsibility to ensure your agent complies with applicable laws.
|
||||
|
||||
Where an Eve agent communicates with people, you may be required to disclose that they are interacting with an automated AI system where law requires it. Eve does not add this disclosure automatically; configure it in your instructions and/or channel responses.
|
||||
|
||||
## What to read next
|
||||
|
||||
- [Tools](./tools): typed actions, the next capability to add
|
||||
|
||||
@@ -7,6 +7,8 @@ Eve is a framework for building durable agents as ordinary files in a TypeScript
|
||||
|
||||
Instead of one large configuration object, each part of your agent gets a clear home. Instructions go in one file, tools in one folder, channels in another. Eve discovers that structure and turns it into an agent that runs locally, serves HTTP, connects to other platforms, and keeps working across many turns.
|
||||
|
||||
Eve is currently in beta and subject to the [Vercel beta terms](https://vercel.com/docs/release-phases/public-beta-agreement). The framework, APIs, documentation, and behavior may change before general availability.
|
||||
|
||||
## An Eve project at a glance
|
||||
|
||||
A small Eve app looks like this:
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
title: "Legal"
|
||||
description: "Preview status, deployer responsibility, and safeguards to review before using Eve with sensitive, regulated, or production data."
|
||||
---
|
||||
|
||||
Eve is currently a preview and subject to the Vercel beta terms; the framework, APIs, documentation, and behavior may change before general availability.
|
||||
|
||||
As the deployer, it is your responsibility to ensure your agent complies with applicable laws.
|
||||
|
||||
You are responsible for configuring approval policies, tool restrictions, connection scopes, route/session authorization, sandbox controls, telemetry exports, and other safeguards appropriate for your use case.
|
||||
|
||||
Before using Eve with non-public, sensitive, regulated, or production data, review which default tools, custom tools, MCP tools, shell/file/web tools, connected services, subagents, schedules, and external actions are available to the agent.
|
||||
|
||||
Require human approval or other safeguards for sensitive, irreversible, regulated, financial, healthcare, employment, housing, legal, safety-impacting, user-impacting, or external side-effecting actions.
|
||||
|
||||
Unless you configure stricter controls, Eve agents may operate with permissive settings, including tool execution without human approval where approval is omitted and sandbox network egress that is not deny-all. Do not rely on model behavior alone to prevent sensitive or irreversible actions.
|
||||
@@ -2,6 +2,7 @@
|
||||
"pages": [
|
||||
"introduction",
|
||||
"getting-started",
|
||||
"legal",
|
||||
"---",
|
||||
"agent-config",
|
||||
"instructions",
|
||||
|
||||
@@ -5,6 +5,8 @@ description: "Reference for every eve CLI command: init, info, build, start, dev
|
||||
|
||||
The `eve` binary (`bin: eve`) runs from your app root, and every command first loads `.env`/`.env.local` from that root. Running `eve` with no command runs `eve dev`.
|
||||
|
||||
Eve is currently a preview and subject to the Vercel beta terms; the framework, APIs, documentation, and behavior may change before general availability.
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | Description |
|
||||
|
||||
@@ -7,6 +7,8 @@ The sandbox is the agent's isolated bash environment: a filesystem rooted at `/w
|
||||
|
||||
A working sandbox exists by default, with nothing to author. Override it only to add setup, seed files, pick a backend, or lock down the network.
|
||||
|
||||
The default sandbox is not a substitute for configuring network policy, credentials, retention, deletion, or other controls your application requires.
|
||||
|
||||
## Using the sandbox
|
||||
|
||||
The model already has shell and file access through the default tools:
|
||||
@@ -164,6 +166,8 @@ There are two hooks, scoped differently:
|
||||
- **`bootstrap({ use })`** is template-scoped and runs once when the template is built. Put reusable setup here that every later session inherits, such as cloning a baseline repo, installing dependencies, or seeding files. Call `use()` to get a `SandboxSession`. Only template filesystem state and supported backend metadata carry into later sessions; config like network policy does not. If external inputs affect what bootstrap produces, set `revalidationKey: () => string` so Eve knows when to rebuild the template (authored sandbox source and seed contents are already tracked for you).
|
||||
- **`onSession({ use, ctx })`** is durable-session-scoped and runs once per session. Put per-session setup here, including network policy, resources, timeout, per-user credentials, and one-time markers. Because it runs inside the active runtime context, it can read `ctx.session` and derive the current principal without baking credentials into the template. Call `use(opts?)` to get a `SandboxSession`; `opts` flow to the backend's update path after create.
|
||||
|
||||
If you require a network policy or other configuration for every session, configure it on the backend factory or in `onSession`; do not rely on bootstrap-only configuration.
|
||||
|
||||
```ts
|
||||
import { defineSandbox } from "eve/sandbox";
|
||||
import { vercel } from "eve/sandbox/vercel";
|
||||
@@ -195,6 +199,8 @@ networkPolicy: {
|
||||
};
|
||||
```
|
||||
|
||||
Default egress is `allow-all`. For non-public, sensitive, regulated, or production workloads, configure `deny-all` or an explicit allow-list before running untrusted tools or handling sensitive data.
|
||||
|
||||
Set it on the factory (`vercel({ networkPolicy: "deny-all" })`) and it applies before authored `bootstrap` code runs; framework-owned base setup may briefly keep egress open to install required packages. Set it in `onSession`'s `use()` to override per-session. The common pattern combines both: leave the factory open so `bootstrap` can `git clone`, then lock down in `onSession`. To change the policy mid-turn, call `sandbox.setNetworkPolicy(...)` on the live handle.
|
||||
|
||||
Domain-level allow-lists and credential brokering are supported by `vercel()` and `microsandbox()`. The Docker backend honors only `"allow-all"` and `"deny-all"` (at creation and via `setNetworkPolicy`); the just-bash backend rejects `setNetworkPolicy` entirely.
|
||||
|
||||
@@ -18,6 +18,8 @@ Every agent gets an `agent` tool by default. The model calls it to delegate a su
|
||||
|
||||
The copy shares the parent's sandbox and tools, and a child's file writes are immediately visible to the parent. That is what makes parallel calls natural: fan out a few copies to fix different files at once. The copy inherits auth and connections, but starts with fresh conversation history and fresh state. If a declared subagent calls `agent`, the child is a copy of _that_ subagent, not the root.
|
||||
|
||||
The parent transfers data to the child through the `message` input it gives the subagent. Do not include sensitive data in a subagent request unless that child and its inherited tools, connections, sandbox, and telemetry path are appropriate for that data.
|
||||
|
||||
An authored tool at `agent/tools/agent.ts` takes priority over the built-in.
|
||||
|
||||
## Declared subagents
|
||||
@@ -86,6 +88,8 @@ A declared subagent's tool name is the bare path-derived name, with no prefix. `
|
||||
|
||||
Because the name lives in the same runtime tool namespace as authored tools, a subagent named `researcher` collides with a tool named `researcher`. Eve rejects the build rather than picking a winner, so keep subagent directory names distinct from tool names.
|
||||
|
||||
Do not rely on subagent delegation by itself as an approval boundary. Put sensitive tools behind `needsApproval`, connection approval, route/session authorization, or other controls wherever those tools can be called.
|
||||
|
||||
Each delegated subagent spins up its own child session and stream. The parent stream carries only the control-plane events `subagent.called` and `subagent.completed`. To follow the child's full progress, read `subagent.called.data.childSessionId` and subscribe at `GET /eve/v1/session/:childSessionId/stream`.
|
||||
|
||||
## When to split
|
||||
|
||||
@@ -68,6 +68,8 @@ export default defineTool({
|
||||
| `once()` | Require approval only the first time the tool runs in a session; auto-allow after. |
|
||||
| `always()` | Require approval before every call. |
|
||||
|
||||
By default, omitted `needsApproval` behaves like `never()`, so tool calls may execute without human approval. Require human approval or other safeguards for sensitive, irreversible, regulated, financial, healthcare, employment, housing, legal, safety-impacting, user-impacting, or external side-effecting actions.
|
||||
|
||||
When the decision depends on the input, pass your own predicate instead of a helper. It receives `{ toolName, toolInput, approvedTools }` and returns a boolean. `toolInput` can be undefined, so guard the access. To require approval only when an amount crosses a threshold:
|
||||
|
||||
```ts
|
||||
@@ -99,6 +101,8 @@ toModelOutput(output) {
|
||||
|
||||
`toModelOutput` receives the full, typed `execute` return and only affects the model. Channel event handlers and hooks still get the full output on `action.result`, so a channel can render rich platform output (Slack Block Kit, say) the model never sees. Return `{ type: "text", value }` for a summary, or `{ type: "json", value }` for a smaller object.
|
||||
|
||||
Do not return secrets, credentials, unnecessary personal data, or unbounded sensitive content from tools. Filter, minimize, and redact tool outputs before returning them.
|
||||
|
||||
## What to read next
|
||||
|
||||
- [Skills](./skills): on-demand procedures the model loads when relevant
|
||||
|
||||
@@ -6,6 +6,20 @@ You author an agent as a directory on disk. The directory is the contract — ma
|
||||
|
||||
The framework is called Eve. The published npm package is `eve`. The CLI binary is `eve`.
|
||||
|
||||
## Preview Terms and Safeguards
|
||||
|
||||
Eve is currently a preview and subject to the Vercel beta terms; the framework, APIs, documentation, and behavior may change before general availability.
|
||||
|
||||
As the deployer, it is your responsibility to ensure your agent complies with applicable laws.
|
||||
|
||||
You are responsible for configuring approval policies, tool restrictions, connection scopes, route/session authorization, sandbox controls, telemetry exports, and other safeguards appropriate for your use case.
|
||||
|
||||
Before using Eve with non-public, sensitive, regulated, or production data, review which default tools, custom tools, MCP tools, shell/file/web tools, connected services, subagents, schedules, and external actions are available to the agent.
|
||||
|
||||
Require human approval or other safeguards for sensitive, irreversible, regulated, financial, healthcare, employment, housing, legal, safety-impacting, user-impacting, or external side-effecting actions.
|
||||
|
||||
Unless you configure stricter controls, Eve agents may operate with permissive settings, including tool execution without human approval where approval is omitted and sandbox network egress that is not deny-all. Do not rely on model behavior alone to prevent sensitive or irreversible actions.
|
||||
|
||||
## What Eve Prioritizes
|
||||
|
||||
- Markdown-first authoring for instructions and procedures
|
||||
|
||||
@@ -3,13 +3,19 @@ import pc from "picocolors";
|
||||
import { resolveInstalledPackageInfo } from "#internal/application/package.js";
|
||||
|
||||
export const EVE_WORDMARK = "eve";
|
||||
export const EVE_BETA_TERMS_URL = "https://vercel.com/docs/release-phases/public-beta-agreement";
|
||||
export const EVE_PREVIEW_NOTICE =
|
||||
"Eve is currently a preview and subject to the Vercel beta terms; the framework, APIs, documentation, and behavior may change before general availability.";
|
||||
|
||||
/**
|
||||
* The one-line boot banner shared by every CLI command that announces itself:
|
||||
* the eve badge plus the installed version, dimmed. Printed only by the CLI
|
||||
* program's pre-action hook so commands never compose their own variant.
|
||||
* The boot banner shared by every CLI command that announces itself: the eve
|
||||
* badge plus the installed version, followed by the preview notice. Printed
|
||||
* only by the CLI program's pre-action hook so commands never compose their
|
||||
* own variant.
|
||||
*/
|
||||
export function eveCliBanner(): string {
|
||||
const { version } = resolveInstalledPackageInfo();
|
||||
return `${pc.bgBlack(pc.white(` ${EVE_WORDMARK} `))} ${pc.dim(`v${version}`)}`;
|
||||
return `${pc.bgBlack(pc.white(` ${EVE_WORDMARK} `))} ${pc.dim(`v${version}`)}\n${pc.dim(
|
||||
EVE_PREVIEW_NOTICE,
|
||||
)}`;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { basename, join, resolve } from "node:path";
|
||||
import pc from "picocolors";
|
||||
|
||||
import { isCodingAgentLaunch } from "#cli/agent-detection.js";
|
||||
import { EVE_WORDMARK } from "#cli/banner.js";
|
||||
import { EVE_PREVIEW_NOTICE, EVE_WORDMARK } from "#cli/banner.js";
|
||||
import { DEFAULT_AGENT_MODEL_ID } from "#shared/default-agent-model.js";
|
||||
import { SPINNER_FRAME_MS, SPINNER_FRAMES } from "#setup/cli/rail-log.js";
|
||||
import { formatNodeEngineOverrideWarning, type NodeEngineOverride } from "#setup/node-engine.js";
|
||||
@@ -62,6 +62,9 @@ const defaultDependencies: InitCommandDependencies = {
|
||||
|
||||
const CURRENT_DIRECTORY_PROJECT_NAME = ".";
|
||||
const ALLOWED_CREATE_IN_PLACE_ENTRIES = new Set([".DS_Store", ".git", ".gitkeep", ".hg"]);
|
||||
function withPublicBetaNotice(message: string): string {
|
||||
return `${message}\n${pc.dim(EVE_PREVIEW_NOTICE)}`;
|
||||
}
|
||||
|
||||
/** Resolves `target` to an existing directory, or undefined for name mode. */
|
||||
async function resolveTargetDirectory(
|
||||
@@ -254,13 +257,21 @@ export async function runInitCommand(
|
||||
dependencies,
|
||||
);
|
||||
freshScaffold = true;
|
||||
logger.log(`${pc.green("✓")} Created an ${EVE_WORDMARK} agent in ${pc.bold(projectPath)}`);
|
||||
logger.log(
|
||||
withPublicBetaNotice(
|
||||
`${pc.green("✓")} Created an ${EVE_WORDMARK} agent in ${pc.bold(projectPath)}`,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
const addition = await addToExistingProject(existingDirectory, options, dependencies);
|
||||
packageManager = addition.packageManager;
|
||||
projectPath = existingDirectory;
|
||||
freshScaffold = false;
|
||||
logger.log(`${pc.green("✓")} Added an ${EVE_WORDMARK} agent to ${pc.bold(projectPath)}`);
|
||||
logger.log(
|
||||
withPublicBetaNotice(
|
||||
`${pc.green("✓")} Added an ${EVE_WORDMARK} agent to ${pc.bold(projectPath)}`,
|
||||
),
|
||||
);
|
||||
if (addition.nodeEngineOverride !== undefined) {
|
||||
logger.log(pc.yellow(`⚠ ${formatNodeEngineOverrideWarning(addition.nodeEngineOverride)}`));
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { describe, expect, it } from "vitest";
|
||||
import type { AgentInfoResult, AgentInfoToolEntry } from "#client/index.js";
|
||||
|
||||
import { AGENT_HEADER_TIPS, buildAgentHeader, pickAgentHeaderTip } from "./agent-header.js";
|
||||
import { EVE_BETA_TERMS_URL } from "#cli/banner.js";
|
||||
import { createTheme } from "./theme.js";
|
||||
|
||||
const FRAMEWORK_TOOL: AgentInfoToolEntry = {
|
||||
@@ -111,23 +112,25 @@ const INFO: AgentInfoResult = {
|
||||
|
||||
describe("buildAgentHeader", () => {
|
||||
const theme = createTheme({ color: false, unicode: false });
|
||||
const previewLine = ` Public preview: ${EVE_BETA_TERMS_URL}`;
|
||||
|
||||
it("renders one brand line with the agent name and nothing else", () => {
|
||||
it("renders the brand line with the agent name and preview label", () => {
|
||||
const lines = buildAgentHeader({ name: "agent-subagents", info: INFO, theme, width: 120 });
|
||||
|
||||
expect(lines).toEqual([" eve agent-subagents"]);
|
||||
expect(lines).toEqual([" eve agent-subagents", previewLine]);
|
||||
});
|
||||
|
||||
it("renders the same brand line when info is unavailable", () => {
|
||||
it("renders the same brand and preview lines when info is unavailable", () => {
|
||||
expect(buildAgentHeader({ name: "weather-agent", theme, width: 120 })).toEqual([
|
||||
" eve weather-agent",
|
||||
previewLine,
|
||||
]);
|
||||
});
|
||||
|
||||
it("renders the tip line for local sessions only", () => {
|
||||
const tip = AGENT_HEADER_TIPS[0]!;
|
||||
const local = buildAgentHeader({ name: "weather-agent", info: INFO, theme, width: 120, tip });
|
||||
expect(local).toEqual([" eve weather-agent", ` ${tip}`]);
|
||||
expect(local).toEqual([" eve weather-agent", previewLine, ` ${tip}`]);
|
||||
|
||||
const remote = buildAgentHeader({ name: "weather-agent", info: INFO, theme, width: 120 });
|
||||
expect(remote.join("\n")).not.toContain("/channels");
|
||||
@@ -140,8 +143,8 @@ describe("buildAgentHeader", () => {
|
||||
};
|
||||
const lines = buildAgentHeader({ name: "weather-agent", info, theme, width: 120 });
|
||||
|
||||
expect(lines[1]).toContain("1 error");
|
||||
expect(lines[1]).toContain("2 warnings");
|
||||
expect(lines.some((line) => line.includes("1 error"))).toBe(true);
|
||||
expect(lines.some((line) => line.includes("2 warnings"))).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
import type { AgentInfoResult } from "#client/index.js";
|
||||
import { EVE_BETA_TERMS_URL } from "#cli/banner.js";
|
||||
import type { Theme } from "./theme.js";
|
||||
import { truncate } from "./tool-format.js";
|
||||
|
||||
@@ -52,6 +53,9 @@ export function buildAgentHeader(input: AgentHeaderInput): string[] {
|
||||
const lines: string[] = [];
|
||||
const brand = c.bold("eve");
|
||||
lines.push(` ${brand} ${c.dim(truncate(name, Math.max(8, width - 8)))}`);
|
||||
lines.push(
|
||||
` ${c.dim(truncate(`Public preview: ${EVE_BETA_TERMS_URL}`, Math.max(8, width - 2)))}`,
|
||||
);
|
||||
|
||||
if (info && (info.diagnostics.discoveryErrors > 0 || info.diagnostics.discoveryWarnings > 0)) {
|
||||
const parts: string[] = [];
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user