# Eve project layout

> Authored slots under `agent/`, path-derived naming, workspace seeding rules, and subagent package boundaries.

- Repository: withastro/flue-with-vercel-eve
- GitHub: https://github.com/withastro/flue
- Human docs: https://www.grok-wiki.com/public/docs/withastro-flue-with-vercel-eve-f4b79875fff6
- Complete Markdown: https://www.grok-wiki.com/public/docs/withastro-flue-with-vercel-eve-f4b79875fff6/llms-full.txt

## Source Files

- `vercel-eve:docs/reference/project-layout.md`
- `vercel-eve:docs/agent-config.md`
- `vercel-eve:docs/meta.json`
- `vercel-eve:apps/fixtures/weather-agent/agent/instructions.md`
- `vercel-eve:apps/fixtures/weather-agent/agent/skills/get-weather.md`
- `vercel-eve:apps/fixtures/weather-agent/agent/tools/get_weather.ts`

---

---
title: "Eve project layout"
description: "Authored slots under `agent/`, path-derived naming, workspace seeding rules, and subagent package boundaries."
---

Eve treats the filesystem as the agent contract: discovery walks `agent/` (or a flat app root), classifies each entry into an authored slot, derives stable names from paths, and compiles inspectable artifacts under `.eve/`. The root agent id comes from `package.json` `name` (or the app-root directory name); subagent ids come from their directory names under `subagents/`.

## Nested vs flat layout

Eve resolves two project layouts from the current working directory upward.

| Layout | `appRoot` | `agentRoot` | When to use |
| ------ | --------- | ----------- | ----------- |
| **Nested** (recommended) | Directory with `package.json` or `vercel.json` | `agent/` child of `appRoot` | Keeps npm project metadata separate from the authored surface |
| **Flat** | Same as `agentRoot` | App root containing recognized slot entries | Supported when the app root is also the agent root |

:::files
my-agent/
├── package.json
├── tsconfig.json
├── agent/
│   ├── agent.ts
│   ├── instructions.md
│   ├── tools/
│   ├── skills/
│   ├── connections/
│   ├── sandbox/
│   ├── channels/
│   ├── subagents/
│   ├── schedules/
│   ├── hooks/
│   └── lib/
└── evals/
:::

`evals/` lives at the app root as a sibling of `agent/`, not inside it. A flat layout co-locates slot files at the app root (`agent.ts`, `instructions.md`, `tools/`, etc.) when no `agent/` directory is present.

Compared to Flue, which resolves a configurable source root (`.flue/` or `src/`) and composes agents through `app.ts`, Eve keeps the authored surface in `agent/` slots that discovery walks directly. See [Flue project layout](/flue-project-layout) for the parallel model.

## Path-derived naming

Identity comes from the path. You never write a `name` or `id` field on a `define*` call — the compiler rejects authored `name` fields on tools.

| Authored path | Resolves to | Notes |
| ------------- | ----------- | ----- |
| `agent/tools/get_weather.ts` | tool `get_weather` | Nested paths flatten: `tools/billing/refund.ts` → `billing-refund` |
| `agent/connections/linear.ts` | connection `linear` | Connection tools appear as `connection__<connection>__<tool>` |
| `agent/skills/get-weather.md` | skill `get-weather` | Flat `.md` or module; or packaged `skills/<name>/SKILL.md` |
| `agent/subagents/researcher/agent.ts` | subagent `researcher` | Bare name in the runtime tool namespace — no prefix |
| `agent/hooks/on-turn.ts` | hook `on-turn` | Recursive directories supported |

**Root agent id:** `package.json` `name` when present, otherwise `basename(appRoot)`. In nested layout with `agent/` as the agent root, the package name wins over the directory basename (so CI paths like `/vercel/path0` do not become the agent id).

**Subagent id:** the directory name under `subagents/<id>/`, or the module basename for single-file subagents (`subagents/researcher.ts`).

Subagent tool names share the same namespace as authored tools. A subagent named `researcher` collides with a tool named `researcher`; Eve rejects the build rather than picking a winner.

## Authored slot reference

Each top-level entry under `agent/` (or a subagent package root) maps to one slot. Discovery classifies entries and emits diagnostics for unsupported or misplaced files.

| Slot path | Purpose | Subagents | Root-only |
| --------- | ------- | --------- | --------- |
| `agent.ts` | Runtime config via `defineAgent` (model, compaction, build, experimental) | Yes | — |
| `instructions.md` / `instructions.ts` / `instructions/` | Base system prompt | Optional | Required on root |
| `instrumentation.ts` | OTel exporter and AI SDK span settings | No | Yes |
| `channels/` | HTTP and messaging entrypoints | No | Yes |
| `connections/` | External MCP or OpenAPI connections | Yes | — |
| `hooks/` | Lifecycle and stream-event subscribers | Yes | — |
| `skills/` | On-demand procedures and capability packs | Yes | — |
| `lib/` | Shared helper modules (import-only) | Yes | — |
| `sandbox.ts` or `sandbox/sandbox.ts` | Single sandbox override | Yes | — |
| `sandbox/workspace/**` | Files seeded into the sandbox | Yes | — |
| `tools/` | Typed executable integrations | Yes | — |
| `schedules/` | Recurring jobs (`.ts` module or `.md` with `cron:` frontmatter) | No | Yes |
| `subagents/` | Specialist child agents | Yes | — |

`agent.ts` is optional on the root agent. When omitted, Eve defaults to `anthropic/claude-sonnet-4.6`. When present, `model` is required. Subagents always require `agent.ts` with a `description` so the parent can decide when to delegate.

### Weather-agent fixture

The `weather-agent` fixture shows the minimal nested layout:

```text
weather-agent/
├── package.json          # name: "weather-agent"
└── agent/
    ├── agent.ts          # defineAgent({ model: "openai/gpt-5.5", ... })
    ├── instructions.md   # always-on system prompt
    ├── skills/
    │   └── get-weather.md
    └── tools/
        └── get_weather.ts
```

The skill frontmatter supplies a `description`; the tool uses `defineTool` with a Zod `inputSchema`. Discovery maps `get-weather.md` → skill `get-weather` and `get_weather.ts` → tool `get_weather`.

## Workspace seeding rules

Eve does not mount the entire `agent/` tree into the sandbox. Only two authored sources land in the runtime workspace:

| Source | Sandbox path | When |
| ------ | ------------ | ---- |
| `skills/` files | `/workspace/skills/<skill-id>/...` | Session bootstrap (and prewarm templates) |
| `sandbox/workspace/**` | `/workspace/...` | Session bootstrap |

Everything under `lib/` stays import-only TypeScript and never reaches the workspace. Skills are materialized as packages under `/workspace/skills/<name>/` with at minimum a `SKILL.md` body; the runtime `loadSkill` tool reads from that path and strips YAML frontmatter before returning markdown to the model.

Use top-level `sandbox.ts` for a definition-only sandbox override. Use `sandbox/sandbox.ts` plus `sandbox/workspace/**` when you also need seeded files. When neither is authored, the framework default sandbox applies.

Subagents seed their own skills and workspace files independently — they do not inherit the parent's sandbox contents. Skill seeds differ per agent node, so a declared subagent with its own `skills/` directory gets its own `/workspace/skills/...` tree.

## Subagent package boundaries

A declared subagent lives under `agent/subagents/<id>/` and is discovered as its own agent root. Its location under `subagents/` is the only marker that makes it a subagent.

:::files
agent/subagents/researcher/
├── agent.ts            # required — must export description
├── instructions.md     # optional (unlike root)
├── connections/
├── hooks/
├── skills/
├── lib/
├── sandbox/
├── tools/
└── subagents/          # nested subagents supported
:::

**Isolation rule:** a declared subagent inherits nothing from the root's authored slots. Discovery treats `subagents/<id>/` as a fresh agent root. An absent slot falls back to the framework default, not the parent's version.

| Slot | Declared subagent | Built-in `agent` tool (copy of parent) |
| ---- | ----------------- | -------------------------------------- |
| Instructions | Own `instructions.{md,ts}`, optional | Inherited |
| Tools, connections, skills, hooks | Own directories | Inherited |
| Sandbox | Own `sandbox/`, else framework default | Shared with parent |
| Channels, schedules | Not supported | Root-only |
| State (`defineState`) | Fresh per child | Fresh per child |

`agent.ts` is required on every declared subagent. The compiler rejects subagents missing `description` on `defineAgent`. Remote subagent definitions (`kind: "remote"`) cannot include local package entries such as `tools/` or `skills/`.

The built-in `agent` tool is the exception: children are copies of the same agent, sharing the parent's sandbox and tools. An authored tool at `agent/tools/agent.ts` takes priority over the built-in.

Nested subagents compile depth-first: each subagent may declare further subagents under its own `subagents/` directory, producing a flat node graph with parent→child edges at compile time.

## Verify discovery

<Steps>
<Step title="Run eve info">

From the app root:

```bash
eve info
```

Lists the discovered surface: layout, model, instructions path, skill names, tool names, channels, and discovery diagnostics.

</Step>
<Step title="Inspect JSON output">

For scripting or CI checks:

```bash
eve info --json
```

Returns `appRoot`, `agentRoot`, `layout`, `skills`, `tools`, `diagnostics`, and paths to artifacts under `.eve/` (`discoveryManifest`, `compiledManifest`, `diagnostics`, `moduleMap`, `metadata`).

</Step>
<Step title="Fix discovery errors">

When a file is not discovered:

1. Confirm it sits in the correct slot per the slot table above.
2. Check root-vs-subagent boundaries (`channels/` and `schedules/` are root-only; `schedules/` inside a subagent is invalid).
3. Ensure the root agent has `instructions.md` (or `.ts` / directory form).
4. Re-run `eve build` or `eve dev` after fixes; inspect `.eve/` artifacts for the full diagnostic list.

</Step>
</Steps>

<ResponseField name="status" type="string">
Compile and discovery status. `unavailable` when artifacts have not been built yet.
</ResponseField>

<ResponseField name="diagnostics" type="object">
Error and warning counts from discovery. Non-zero errors block compilation.
</ResponseField>

## Related pages

<CardGroup cols={2}>
<Card title="Eve quickstart" href="/eve-quickstart">
Run `eve init`, start `eve dev`, and send the first session message.
</Card>
<Card title="Eve authoring surfaces" href="/eve-authoring-surfaces">
Configure `agent.ts`, instructions, tools, skills, connections, sandbox, and subagents from the filesystem contract.
</Card>
<Card title="Eve weather fixture" href="/eve-weather-fixture">
Walk through the `weather-agent` fixture end to end.
</Card>
<Card title="Flue project layout" href="/flue-project-layout">
Compare Eve's `agent/` slots with Flue's source-root resolution and `app.ts` composition.
</Card>
</CardGroup>
