# Calaf seed file format (`calaf_seed: 1`)

A **seed** is one JSON document that stocks a [Calaf](https://calaf.ai) workspace:
organizations to pursue, outreach templates, interview prep, and (shown, not
applied) the vocabulary and planner settings the seed was designed around. A
user imports it at **Settings → Workspace → Seeds**, previews exactly what each
part would add, and chooses what lands.

This page is written for AI assistants as much as for people. If a user asks
you to "write me a Calaf seed", produce **one JSON document in this format and
nothing else** — no prose around it, no code fence required.

If your client speaks MCP, Calaf serves this same loop as a server at
**`https://calaf.ai/api/mcp`** (Streamable HTTP, no auth): `get_seed_format`
returns this document, and `validate_seed` runs a draft through the app's real
importer and reports every issue with its exact path. Without MCP, `POST` the
draft document to **`https://calaf.ai/api/seed-validate`** for the same
verdict. Either way: validate and fix before you deliver the file.

Nothing in a seed file is ever executed or obeyed. It becomes ordinary rows the
user can edit or delete, exactly like notes they typed themselves.

## Envelope

```json
{
  "calaf_seed": 1,
  "meta": { "name": "PE Associate Recruiting", "blurb": "Funds that hire MBA associates", "author": null, "domain": null }
}
```

- `calaf_seed` — required, must be exactly the number `1`.
- `meta.name` — required. `blurb`, `author`, `domain` — optional; displayed, never trusted.

**Every other section is optional.** A file that is nothing but forty
organizations is a perfectly good seed.

## Sections

### `orgs` — up to 500

The organizations to pursue.

```json
{ "name": "Audax Group", "tier": "Middle market", "location": "Boston", "kind": "fund", "groups": "Tech, Healthcare", "why": "Active MBA associate hiring" }
```

`name` is required. `kind` should match one of your `orgKinds` keys. `tier`
should be one of that kind's tier bands.

### `contacts` — up to 200

People, matched to organizations by **name** (a file carries no ids). An
unmatched person still lands, unattached, rather than being dropped.

```json
{ "first_name": "Dana", "last_name": "Reyes", "title": "Principal", "org": "Audax Group", "notes": null }
```

**People are the risky half.** Calaf always imports them un-ticked so the user
reviews each one first — a firm an assistant invented wastes an afternoon; a
person it invented is an email to someone who does not exist. Only include a
person when you are certain they hold that role today.

### `templates` — up to 50

Outreach email templates. Merge fields available: `{{first_name}}`, `{{firm}}`,
`{{office}}`, `{{group}}`, `{{my_name}}`, `{{my_school}}`, `{{my_year}}`.

```json
{ "name": "Cold intro", "category": "Outreach", "subject": "Quick question about {{firm}}", "body": "Hi {{first_name}}, …" }
```

### `prep` — up to 500

Interview prep questions, optionally with an answer framework.

```json
{ "category": "Technical", "question": "Walk me through a paper LBO.", "answer": "Start from the purchase price…" }
```

### `orgKinds` — up to 6

What kinds of organization this seed tracks, each with its own tier bands
(up to 12 per kind).

```json
{ "key": "fund", "label": "Fund", "tiers": ["Mega", "Upper middle market", "Middle market"] }
```

### `ladder` — up to 4 round names, in order

The interview rounds this kind of employer actually runs.

```json
["Coffee chat screen", "Modeling test", "Final round"]
```

### `vocab` and `planner` — shown, not applied

```json
"vocab":   { "firm": "fund", "firms": "funds", "person": "investor", "finalRound": "final round", "prepNoun": "technicals" },
"planner": { "engine": "ratios", "appToFirst": 0.25 }
```

The import preview displays these so the user sees what the seed was designed
around, but how a workspace *reads* comes from its primary seed — a file's
config is not applied. `appToFirst` is a conversion **rate** in (0, 1], not a
percentage.

### `keyDates` — up to 50 (reserved)

```json
{ "label": "On-cycle kickoff", "on": "2026-09-15" }
```

Read and validated (`on` must be a real ISO calendar day) but **not imported
yet** — the preview says so. Included in the format so files written today
survive the feature landing.

## Ceilings and cleaning

Per file: 500 orgs, 200 contacts, 50 templates, 500 prep questions, 6 org
kinds, 12 tier bands per kind (each ≤ 40 characters), 4 ladder rounds, 50 key
dates. String lengths by role: names ≤ 120, labels ≤ 60, short text ≤ 200,
template bodies ≤ 8000, notes ≤ 4000. The whole file must be under 4 MB.

The parser is deliberately forgiving: a bad row is **dropped and reported**,
never fatal; overlong strings are truncated and reported; rows past a ceiling
are left out and reported; unknown fields are ignored. Invisible and
bidirectional-control characters are stripped from every string. The import
preview lists every issue with its path, so an assistant-authored file gets
precise feedback.

## Rules for assistants writing a seed

1. Organizations confidently; **people only where you are certain they hold
   that role today.**
2. Leave a field out rather than guessing at it — a blank is useful, a wrong
   answer costs the user a wasted conversation.
3. Give a source for every factual claim (in your reply to the user, not
   inside the file).
4. Dates only when you are sure.
5. Output **only** the JSON document.

## Complete example

```json
{
  "calaf_seed": 1,
  "meta": { "name": "PE Associate Recruiting", "blurb": "Funds that hire MBA associates" },
  "orgKinds": [{ "key": "fund", "label": "Fund", "tiers": ["Mega", "Middle market"] }],
  "ladder": ["Coffee chat screen", "Modeling test", "Final round"],
  "planner": { "engine": "ratios", "appToFirst": 0.25 },
  "orgs": [{ "name": "Audax Group", "tier": "Middle market", "location": "Boston", "kind": "fund" }],
  "contacts": [{ "first_name": "Dana", "last_name": "Reyes", "title": "Principal", "org": "Audax Group" }],
  "templates": [{ "name": "Cold intro", "category": "Outreach", "subject": "Quick question about {{firm}}", "body": "Hi {{first_name}}," }],
  "prep": [{ "category": "Technical", "question": "Walk me through a paper LBO." }],
  "keyDates": [{ "label": "On-cycle kickoff", "on": "2026-09-15" }]
}
```
