> ## Documentation Index
> Fetch the complete documentation index at: https://loop-js.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Prompts

> One Prompt shape, three forms, three homes — goal, execute, verify

A **Prompt** is the judgment-bearing text you own. One shape, three forms:

* a **string literal** — never touches disk;
* **`{ file: "./verify.md" }`** — re-read fresh at the start of every Round;
* a **per-round function** `(ctx) => string` (sync or async).

## Three homes

Every home takes a Prompt directly:

| Home      | Role                                                           | If omitted         |
| --------- | -------------------------------------------------------------- | ------------------ |
| `goal`    | what "done" means — the set-once objective, judged every Round | required           |
| `execute` | what to work on                                                | the Goal stands in |
| `verify`  | the success criteria the Verify agent judges                   | the Goal stands in |

```ts theme={null}
import { Loop } from "@loop.js/core"

export default Loop.define({
  goal: "Build a playable 2D platformer in ./game",
  execute: { file: "./execute.md" },
  verify: "It builds, `bun test` passes, and the game boots to a controllable character",
})
```

Only `goal` is required — Goal-only is a first-class run mode. The framework ships no
prompt generation: prompts are hand-authored or omitted.

To bind a phase's **model** or **permissions**, use the object form — the bare Prompt is
shorthand for its `prompt` field:

```ts theme={null}
verify: { prompt: { file: "./verify.md" }, model: "claude-haiku-4-5" }
```

<Note>
  `{ file }` next to a binding key (`{ file: "./verify.md", model: "…" }`) is ambiguous —
  is it a Prompt or a binding? — and is refused with a teaching error at startup, never
  guessed at. Write `{ prompt: { file }, model }`.
</Note>

Paths named in a prompt resolve inside the Workspace: with the default layout,
`"./game"` means `workspace/game`.

## File prompts are re-read every Round

`{ file }` is read fresh at the start of each Round. Edit the file while the Loop runs and
the next Round works — and is judged — against the new text: editing `verify.md` mid-loop
re-sets the bar. A missing or unreadable file is a loud error naming the path, never a
silent fallback.

<Note>
  The Execute agent may itself author or revise `verify.md` — every edit is visible in the
  event stream.
</Note>

## Function prompts

The function form receives `PromptCtx` — a deliberately small per-round context, the same
for all three homes; enough to vary the prompt, not a state channel:

```ts theme={null}
goal: (ctx) =>
  ctx.previous
    ? `Address the last verdict first: ${ctx.previous.feedback}`
    : "Build a playable 2D platformer in ./game",
```

`ctx.round` is the 1-based Round number. `ctx.previous.feedback` carries what the last
Round left behind — the Verdict's reason, or the engine's one-liner if the Round was
interrupted; `ctx.previous.verdict` is present when a Verdict was produced.

## Writing a good Verify bar

A good bar names a **testable end-state**, the **checks to run**, and the **invariants
that must hold**. A vaguer bar is judged conservatively: the skeptical Verify agent treats
a claim as evidence, not proof, and insufficient evidence reads as not met.
