Skip to content

Proposal: single-file .agent / .agents format (frontmatter + markdown), rendered through the real discoverAgent #592

Description

@HKTITAN

What problem are you trying to solve?

An eve agent is a directory (agent/agent.ts, agent/instructions.md, agent/tools/*.ts, …). That's ideal for a project you own and grow, but it's heavy for the things people most want to move around:

  • Portability / shareability — you can't paste an agent into a gist, an issue, or a Slack thread without shipping a directory. Skills, prompts, and schedules already circulate as single markdown files because they are single files; whole agents don't get that affordance.
  • Single-file subagents — a subagent is often just a description, a model, and a few lines of instructions, yet today requires a directory with a mandatory agent.ts.
  • Fleet manifests — multi-agent apps encode their delegation structure implicitly in the filesystem; there's no single readable manifest for "root + members + delegation graph + shared connections." (Related: Ideal project structure for multiple root agents with some shared tools / skills #50.)
  • Zero-to-agent barrier — the on-ramp is "learn the directory conventions," not "read one file."

Proposed solution

Two optional single-file surfaces that lower to the exact same AgentSourceManifest a directory walk produces:

  • .agent — one agent: YAML frontmatter (declarative config + capability blocks) + a markdown body that is instructions.md. Idiomatic for eve, which already authors skills / schedules / instructions as gray-matter frontmatter + markdown.
  • .agents — a fleet: one root agent + named members wired by a delegation DAG, sharing connections and defaults.

Minimal .agent:

---
apiVersion: eve/v1
kind: Agent
agent:
  model: anthropic/claude-opus-4.8
tools:
  get_weather: { $ref: ./tools/get_weather.ts }
---

You are a concise weather assistant. Call `get_weather` before answering
any forecast or temperature question, then reply in one line.

The load-bearing design decision: the loader fabricates nothing. It renders the frontmatter into an in-memory agent/ tree and calls the real, unmodified discoverAgent over a createMemoryProjectSource. Identity, slug validation, markdown lowering, subagent recursion, slot collision, and manifest assembly all run through the genuine directory walker — so directory⇄file round-trip and logicalPath / sourceId fidelity are exact by construction. Net new surface: recognition of a *.agent / *.agents file at agent-root resolution + one renderer + one fleet renderer + two zod schemas. Zero changes to normalize-manifest.ts / compileAgentManifest / any normalize-*.ts.

Guiding rule: inline anything eve can serialize; $ref anything eve re-imports at runtime (a bespoke execute, a LanguageModel object, a channel handler → { $ref: "./path.ts#export" }). Identity is always the key — no name field (zod .strict()), matching eve's filesystem-first identity rule. Secrets only via ${env:VAR}.

Full materials — spec, JSON Schemas, runnable examples, a reference loader, and an RFC: https://github.com/HKTITAN/eve-dot-agent-format

I verified every eve-internals claim against vercel/eve @ HEAD before proposing this — the discoverAgent / createMemoryProjectSource seam, defineTool accepting a JSON-Schema inputSchema, defineBashTool / webFetch as public exports, the discovery (v12) / compiled (v33) manifests, Apache-2.0 + DCO — see VERIFICATION.md.

Per CONTRIBUTING (significant change → discuss first), I'm opening this for maintainer feedback before any implementation PR. Glad to iterate on scope, on naming (.agent / .agents vs agent.md / agents.yaml), and on the precedence rules when both a single file and an agent/ directory exist. If there's interest, I'll follow up with a wired-in loader + tests + changeset.

Alternatives considered

  • Pure JSON/JSONC or TOML single-file formats — rejected in favor of frontmatter + markdown because eve already authors skills/schedules/instructions that way (reuses the vendored gray-matter) and the markdown body maps 1:1 to instructions.md.
  • Fabricating SourceRefs directly from the parsed file — rejected; it duplicates the walker and risks logicalPath / sourceId drift. Rendering into a memory ProjectSource reuses the real code path instead.
  • A new declarative tool runtime — rejected; inline tools only wrap shipped primitives (defineBashTool, webFetch); anything bespoke is a $ref.
  • Do nothing — the directory form stays the destination; this is purely an additive on-ramp + portability layer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions