# Eve weather fixture

> Walk through the `weather-agent` fixture: instructions, tool schema, skill procedure, and local dev smoke paths.

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

## Source Files

- `vercel-eve:apps/fixtures/weather-agent/README.md`
- `vercel-eve:apps/fixtures/weather-agent/agent/agent.ts`
- `vercel-eve:apps/fixtures/weather-agent/agent/instructions.md`
- `vercel-eve:apps/fixtures/weather-agent/agent/tools/get_weather.ts`
- `vercel-eve:apps/fixtures/weather-agent/agent/skills/get-weather.md`
- `vercel-eve:apps/fixtures/weather-agent/package.json`
- `vercel-eve:README.md`

---

---
title: "Eve weather fixture"
description: "Walk through the `weather-agent` fixture: instructions, tool schema, skill procedure, and local dev smoke paths."
---

The `weather-agent` fixture at `apps/fixtures/weather-agent/` is a minimal, filesystem-authored Eve app used across the Eve monorepo for local development, manual smoke testing, scenario tests, and Nitro bundle analysis. It exposes one typed tool (`get_weather`), one on-demand skill (`get-weather`), always-on instructions, and a model config in `agent/agent.ts`. The agent id resolves to `weather-agent` from `package.json`.

## Fixture role in the monorepo

| Consumer | How it uses `weather-agent` |
| -------- | --------------------------- |
| Root `pnpm dev` | `scripts/dev.mjs` runs `eve` in watch mode and starts `weather-agent` with `eve dev --no-ui --port 0` |
| Manual smokes | Developers boot the fixture directly and exercise the TUI or HTTP session API |
| Scenario tests | `WEATHER_AGENT_DESCRIPTOR` in `packages/eve/src/internal/testing/scenario-apps/weather-agent.ts` mirrors the fixture for dev-server, CLI, and HMR tests |
| Bundle analysis | `nitro-bundle-report` scenario tests target `apps/fixtures/weather-agent` |

Focused end-to-end eval suites live under `e2e/fixtures/`; the weather fixture itself is the canonical small app for repo-local dev rather than a dedicated eval package.

## Authored layout

:::files
weather-agent/
├── package.json          # scripts: dev, build, start, info, typecheck
├── tsconfig.json         # includes agent/**/* and .eve/**/*.d.ts
├── turbo.json            # build depends on eve#build
└── agent/
    ├── agent.ts          # defineAgent model + provider options
    ├── instructions.md   # always-on system prompt
    ├── tools/
    │   └── get_weather.ts
    └── skills/
        └── get-weather.md
:::

Path-derived naming applies throughout: `agent/tools/get_weather.ts` → tool `get_weather`; `agent/skills/get-weather.md` → skill `get-weather`. No `name` or `id` fields appear on `define*` exports.

```mermaid
flowchart LR
  subgraph client["Client surfaces"]
    TUI["eve dev TUI"]
    HTTP["POST /eve/v1/session"]
  end
  subgraph runtime["Eve runtime"]
    Harness["Harness tool loop"]
    SkillRouter["load_skill + skill catalog"]
  end
  subgraph authored["Authored surface"]
    Instr["instructions.md"]
    Skill["skills/get-weather.md"]
    Tool["tools/get_weather.ts"]
  end
  TUI --> Harness
  HTTP --> Harness
  Harness --> Instr
  Harness --> SkillRouter
  SkillRouter --> Skill
  Harness --> Tool
```

## Runtime config (`agent/agent.ts`)

`defineAgent` sets the model and OpenAI provider options for adaptive thinking:

```ts
import { defineAgent } from "eve";

export default defineAgent({
  model: "openai/gpt-5.5",
  modelOptions: {
    providerOptions: {
      openai: {
        reasoningEffort: "high",
        reasoningSummary: "auto",
      },
    },
  },
});
```

`model` is required when `agent.ts` is present. Provider routing stays BYOC/BYOK: configure the model provider through `/model` in the dev TUI, `.env.local`, or a direct provider SDK override—nothing in the fixture hard-codes a hosted connector beyond the gateway model id string.

## Instructions (`agent/instructions.md`)

The always-on prompt is a single line:

```md
You are a weather-focused assistant. Be concise, accurate, and explicit about when you are using the local weather tool.
```

Eve composes this into every turn. Procedural guidance for weather queries lives in the skill, not here.

## Tool: `get_weather`

`defineTool` from `eve/tools` defines a typed, auto-approved lookup with a Zod input schema and a deterministic stub response.

| Field | Value |
| ----- | ----- |
| File | `agent/tools/get_weather.ts` |
| Model-facing name | `get_weather` |
| Approval | `needsApproval: never()` |
| Input | `{ city: string }` |
| Output | `{ city, temperatureF, condition, summary }` |

<ParamField body="city" type="string" required>
City name to look up. Passed through to the response unchanged.
</ParamField>

<ResponseField name="city" type="string">
Echo of the input city.
</ResponseField>

<ResponseField name="temperatureF" type="number">
Fixed stub value `72`.
</ResponseField>

<ResponseField name="condition" type="string">
Fixed stub value `"Sunny"`.
</ResponseField>

<ResponseField name="summary" type="string">
Human-readable summary, e.g. `Sunny in Brooklyn with a light breeze.`
</ResponseField>

```ts
import { defineTool } from "eve/tools";
import { never } from "eve/tools/approval";
import { z } from "zod";

export default defineTool({
  needsApproval: never(),
  description: "Get the current weather for a city.",
  inputSchema: z.object({
    city: z.string(),
  }),
  async execute(input) {
    const city = input.city;
    await sleep(300); // simulated latency
    return {
      city,
      temperatureF: 72,
      condition: "Sunny",
      summary: `Sunny in ${city} with a light breeze.`,
    };
  },
});
```

The tool does not call an external weather API. The 300 ms delay exercises async tool execution and streaming turn timing. Tools run in the app runtime (not the sandbox), so this pattern is suitable for wiring real HTTP clients later by replacing `execute`.

## Skill: `get-weather`

The flat markdown skill at `agent/skills/get-weather.md` carries YAML frontmatter for routing and a short procedure body:

```md
---
description: Use the weather tool before answering forecast or temperature questions.
---

When the user asks about weather, temperature, or forecast conditions, call the `get_weather` tool before answering.
```

Eve advertises the `description` to the model alongside the framework-owned `load_skill` tool. When a turn matches that description, the model loads the skill body into context, then calls `get_weather` before composing a reply. Loading a skill adds instructions only; `get_weather` stays in the active tool set regardless of whether the skill is loaded.

<Note>
Flat skills can omit frontmatter—Eve falls back to the first body line as the routing hint. The fixture includes an explicit `description` so intent-based routing is reliable.
</Note>

## Package scripts

| Script | Command | Purpose |
| ------ | ------- | ------- |
| `dev` | `eve dev` | Local runtime + interactive TUI |
| `build` | `eve build` | Compile `.eve/` and build host output |
| `start` | `eve start` | Serve built `.output/` |
| `info` | `eve info` | Print discovered tools, skills, routes, diagnostics |
| `typecheck` | `tsgo --noEmit -p tsconfig.json` | Type-check authored modules |

Dependencies: `eve` (workspace) and `zod` (catalog).

## Local development

<Steps>
<Step title="Install and build the monorepo">

From the Eve repo root:

```bash
pnpm install
pnpm build
```

</Step>

<Step title="Start the fixture">

<Tabs>
<Tab title="From fixture directory">

```bash
cd apps/fixtures/weather-agent
pnpm dev
```

Starts `eve dev` with the interactive TUI. The fixture README notes that booting the TUI itself does not require credentials.

</Tab>

<Tab title="From monorepo root">

```bash
pnpm dev
```

Runs `eve` package watch mode and `weather-agent` headlessly (`--no-ui --port 0`). The orchestrator prints `server listening at http://127.0.0.1:<port>` when ready.

</Tab>
</Tabs>

</Step>

<Step title="Verify discovery">

```bash
cd apps/fixtures/weather-agent
pnpm run info
```

Confirm `get_weather` (tool), `get-weather` (skill), and the default Eve channel routes appear. Use `--json` for machine-readable output.

</Step>

<Step title="Smoke a weather turn">

Ask a weather question in the TUI, for example:

```text
What is the weather in Brooklyn?
```

Expected turn order: optional `load_skill` for `get-weather`, then `get_weather` with `city="Brooklyn"`, then an assistant reply citing the stub result. The TUI collapses tool calls to a one-line summary (`✓ get_weather  city="Brooklyn" → 72°F`).

<Warning>
Completing a model turn requires a linked model provider. The dev TUI surfaces missing provider setup as `⚠ 1 setup issue: model provider not linked · /model` before the first message fails.
</Warning>

</Step>
</Steps>

## HTTP smoke paths

The default Eve channel mounts session routes under `/eve/v1/` without an authored `agent/channels/eve.ts`. `localDev()` accepts loopback requests during development.

:::endpoint GET /eve/v1/health
Liveness check. Returns `{ ok: true, status: "ready" }` when the dev server is up.
:::

:::endpoint POST /eve/v1/session
Start a durable session with a user message.
:::

<RequestExample>

```bash
curl -X POST http://127.0.0.1:<port>/eve/v1/session \
  -H 'Content-Type: application/json' \
  -d '{"message":"What is the weather in Brooklyn?"}'
```

</RequestExample>

<ResponseExample>

```json
{
  "ok": true,
  "sessionId": "ses_01h...",
  "continuationToken": "eve:7f3c..."
}
```

The response also sets the `x-eve-session-id` header.

</ResponseExample>

:::endpoint GET /eve/v1/session/:sessionId/stream
Stream NDJSON events for the session (`application/x-ndjson; charset=utf-8`).
:::

<RequestExample>

```bash
curl -N http://127.0.0.1:<port>/eve/v1/session/<sessionId>/stream
```

</RequestExample>

For a weather query, expect at minimum:

| Event | Meaning |
| ----- | ------- |
| `session.started` | Session admitted |
| `actions.requested` | Model requested `get_weather` |
| `action.result` | Tool returned stub weather data |
| `message.completed` | Assistant reply finished |
| `session.completed` | Turn closed |

:::endpoint POST /eve/v1/session/:sessionId
Send a follow-up with the `continuationToken` from the prior response.
:::

<RequestExample>

```bash
curl -X POST http://127.0.0.1:<port>/eve/v1/session/<sessionId> \
  -H 'Content-Type: application/json' \
  -d '{"continuationToken":"<token>","message":"Now do Queens."}'
```

</RequestExample>

Scenario tests in `packages/eve/test/scenarios/dev-server.scenario.test.ts` automate this path: they boot `eve dev --no-ui` against `WEATHER_AGENT_DESCRIPTOR`, hit `/eve/v1/health`, send `"hello world"` through the dev client harness, and assert a `message.completed` event—without requiring live model credentials when `NODE_ENV=test` activates the mock-model adapter.

## Headless and CI-oriented flags

| Flag | Effect |
| ---- | ------ |
| `--no-ui` | Skip the TUI; serve HTTP only (also the default when stdout is not a TTY) |
| `--host 127.0.0.1` | Bind address |
| `--port 0` | Let the OS assign a free port (used by root `pnpm dev`) |
| `--tools auto-collapsed` | Collapse tool call display in the TUI (default) |

## What to copy from this fixture

| Pattern | Fixture file | Reuse for |
| ------- | ------------ | --------- |
| Minimal `defineAgent` with `modelOptions` | `agent/agent.ts` | Model and provider tuning |
| Single-sentence instructions | `agent/instructions.md` | Stable agent identity |
| Typed tool with `never()` approval | `agent/tools/get_weather.ts` | Safe auto-run integrations |
| Flat skill with frontmatter routing | `agent/skills/get-weather.md` | On-demand procedures without prompt bloat |
| Package script wiring | `package.json` | Standard `dev` / `build` / `info` workflow |

## Related pages

<CardGroup>
<Card title="Eve quickstart" href="/eve-quickstart">
Run `eve init`, start `eve dev`, and send the first session message.
</Card>
<Card title="Eve project layout" href="/eve-project-layout">
Authored slots under `agent/` and path-derived naming rules.
</Card>
<Card title="Eve authoring surfaces" href="/eve-authoring-surfaces">
Configure `agent.ts`, instructions, tools, skills, and connections from the filesystem contract.
</Card>
<Card title="Eve sessions and streaming" href="/eve-sessions-streaming">
Session lifecycle, NDJSON events, and `continuationToken` follow-ups.
</Card>
<Card title="Eve HTTP protocol reference" href="/eve-http-protocol-reference">
Full route inventory, event types, and client integration entry points.
</Card>
<Card title="Eve CLI reference" href="/eve-cli-reference">
`eve dev`, `eve info`, `eve build`, and flag defaults.
</Card>
</CardGroup>
