---
name: omega-point-agent-relay
description: Run Omega Point (Eternal Search) for a user, in either of its two versions, both executed on the Eternal Search server. Version 1.5 breaks one research goal into open questions, competing hypotheses and deciding experiments and publishes them on the site; version 2.00 returns one card per significant knowledge gap. Ask the user which version before the first run. Your agent starts the run, follows its status, keeps the user informed and hands over the published result; at present it answers no model calls (the status says run_mode server). When the server hands model calls to agents instead (run_mode agent_relay), the relay sections at the end apply and you answer every call with your own model. Use from Claude Code, Codex, Cursor, Cowork or a plain script. Also use when a user wants the results of an existing Omega Point run by its key (pipeline-...), their own or anyone's, started here or on the site: its published questions and hypotheses with their assessments as markdown files with the structure of their pages, no registration needed.
---

# Omega Point for agents

Omega Point takes one research goal ("restore youthful skin properties in middle-aged adults")
and produces a tree: the requirements behind the goal, the scientific fields that study each,
the questions those fields still leave open, competing hypotheses for each question and the
experiments that would decide between them. A full run is several hundred model calls over
several hours. The engine lives on the Eternal Search server.

**At present every run started through this skill executes on the server.** The start response and
the run status say `run_mode: server`: the server answers every model call itself, you pull no tasks
and serve nothing. Your work is to start the run, follow its status, keep the user informed and hand
over the published result; see "A run on the server". The sections from "Relay mode" to the end
describe the other mode, `run_mode: agent_relay`, in which the server hands every model call to you
as a task; they apply only when the status says so.

## Two versions: ask which one before the first run

Omega Point has two versions. Unless the user already named one, ask in their language which
they want, with this difference in plain words:

- **Omega Point 1.5** (this skill): a run breaks one research goal into open questions and
  competing hypotheses, with the experiments that would decide between them, and publishes them on
  the site, one page per question and per hypothesis, in English and Russian. It can also run on
  the user's own model, with no account, nothing sent to the server and nothing published: download
  the omega-point-1-local skill from https://eternalsearch.net/api/v1/omega1/skill?include=content
  (or the omega_get_local_skill MCP tool), save every file under ~/.claude/skills/omega-point-1-local/
  or ~/.codex/skills/omega-point-1-local/ and follow its SKILL.md. Offer both before the first run.
- **Omega Point 2.00**: the engine reads open full-text papers, finds significant gaps in what is
  known, and returns one card per gap: competing variants from the obvious to the radical, each
  with a causal chain, quoted evidence and a first experiment. Cards are published on
  https://eternalsearch.net/omega after review by the Eternal Search team. It needs this agent
  linked to the user's Eternal Search account, and up to three studies per person run at a time; a
  fourth one waits for a free slot.

Omega Point 2.00 can run in two places. Before the first 2.00 study offer the user both and let
them choose:

- **On the Eternal Search server** (the loop below): the platform models do the work, the agent is
  linked to the user's account, and cards are kept on the site.
- **On the user's own model**, with no account and nothing sent to the server: download the
  omega-point-2-local skill from https://eternalsearch.net/api/v1/omega2/skill?include=content (or
  the omega2_get_skill MCP tool), save every file under ~/.claude/skills/omega-point-2-local/ or
  ~/.codex/skills/omega-point-2-local/ keeping its path, and follow its SKILL.md. It needs an agent
  with files, a shell and subagents (Claude Code, Codex), and the user pays for their own model calls.

### The Omega Point 2.00 loop

You never pull or answer tasks for a 2.00 study; there is nothing for your model to do except talk
to the user.

1. Link the agent to the account if it is not linked: `node omega-connector.mjs login` (then
   `login --wait`), or MCP `omega_login_start` and `omega_login_poll`. Send the user the returned
   URL with the words "open it and press Connect", then wait for the answer and continue by
   yourself; see "Linking". You never open the site, never sign in, never ask for a code or a
   password. An anonymous link is refused with 403.
2. Start: `node omega-connector.mjs study-start "<the question in the user's own words>" --language <their language>`
   (MCP `omega2_start_study`; HTTP `POST https://eternalsearch.net/api/v1/omega2/studies` with
   `{"question": "..."}` and the link token as the Bearer header). Show the user the returned
   `public_id`: it names the study from any session.
3. Follow: `study-status <study>` (MCP `omega2_study_status`). Tell the user its `progress_report` in
   their language, and read `next_action`.
4. Clarifying questions: when the status is `awaiting_user_answer`, run `study-questions <study>`
   (MCP `omega2_list_clarifications`), ask the user each open question in their language, wait for the
   answer, and send it with `study-answer <study> <question_id> --file answer.txt` (MCP
   `omega2_answer_clarification` with one stable `answer_idempotency_key` per answer). Never answer for
   the user.
5. A study runs for hours. Before you end any turn, read the status and tell the user the progress and
   the phrase that continues: "show Omega Point 2 study <study>". The study keeps running on the
   server while no session is open; the account lists it at https://eternalsearch.net/omega/my-runs.
6. Paused, stopped or over its budget: `study-resume <study>` (MCP `omega2_resume_study`) on the user's
   word only.
7. Finished (`completed_cards_ready` or `completed_research_report`): `study-cards <study>` (MCP
   `omega2_cards` and `omega2_card`) and give the user every card in full, never shortened; save
   `study-export <study> --markdown` as a file and tell them where it is. Ask for feedback and store it
   with MCP `omega2_submit_feedback`.

Base URL: `https://eternalsearch.net/omega-point/api/agent/v1`
Protocol: `<base>/openapi.json`. Page: `https://eternalsearch.net/omega-point/agents`.

## A run on the server (Omega Point 1.5, run_mode server)

1. Register a link once (`node omega-connector.mjs register --provider codex`, or any provider: a
   server run does not use it; MCP `omega_register`). Keep the token: `~/.omega-point/link.json`.
2. Ask the three questions of "Before the first run" in one message (Russian versions, poster
   sheets, linking the account) and wait for the answers. If the user wants the account link, run
   `login`, give them the URL and the code, then `login --wait`.
3. Start with the user's question in their own words as the goal (see "The goal is the user's
   question"): `node omega-connector.mjs run "<goal>"` (`--no-russian`, `--posters`; MCP
   `omega_start_run`; HTTP `POST /runs`). The response carries `run_mode: server`, the run key and
   `handoff_text`. Show the user `handoff_text` verbatim at once: they paste it into a new session
   if this one ends, and that session follows the run. Up to three runs per person at a time: when
   the pool is full the response says `queued_position`, and the run starts by itself.
4. Follow the run. `node omega-connector.mjs progress <run_key>` (`GET /runs/<run_key>`,
   `omega_run_status`) carries `progress_report`, written for the user: tell it to them in their
   language before every turn of yours ends, with what comes next. A run takes hours and keeps
   running while no session is open. `serve --run <run_key> --detach` watches it in the background
   and logs every report; nothing is served. `next_action` says in one sentence what to do.
   `keep_serving` is always false for a server run. Do not stop the run.
5. `relay_phase` is `engine` while the engine runs, `finishing` while titles, duplicate checks,
   explanations, headings and translations are written, `done` when nothing more will come. The
   engine status `completed_at_step` is not the end: wait for `done`.
6. `stopped` with `resumable: true`: `node omega-connector.mjs resume <run_key>` (`omega_resume_run`)
   continues it under the same key, on the server. When `error_message` begins with "stopped before
   step 3", the engine stopped on purpose: tell the user the reason and propose a clearer wording;
   resume only if they ask.
7. `done`: `outcome <run_key>` gives the links to every published question and hypothesis (English
   and Russian) and the size of the texts; `documents <run_key>` saves the folder of markdown files
   with the poster sheets; then ask the user for feedback and store it with `feedback`. Details in
   "When the run is done", "Then save the run as files" and "After the run" below; those three
   points apply to both modes.

## Fetch the results of any run by its key

What a run published (its open questions and hypotheses) is public, so anyone can fetch it: a run
you started, a run started on the Eternal Search site, a run of another user. You need only the run
key (`pipeline-` and twelve characters). No link, no token, no registration, no run of your own.
When the user says "fetch the results of pipeline-fbbc235bbe60" (or the same in their language):

```bash
node omega-connector.mjs documents pipeline-fbbc235bbe60            # the folder omega-pipeline-fbbc235bbe60/
node omega-connector.mjs documents pipeline-fbbc235bbe60 --dir out  # or a folder you choose
node omega-connector.mjs outcome pipeline-fbbc235bbe60              # links and text sizes; --texts for the texts
```

The folder holds one markdown file per published open question and per published hypothesis,
per language (`questions/<id>.en.md`, `hypotheses/<id>.ru.md`), each with the text and structure
of its page on the site; an index per language (`index.en.md`, `index.ru.md`) linking every file;
and the poster sheets as PNG files where the run has them. Every hypothesis file ends with the
hypothesis's assessment: eight criteria rated 0 to 10 (support from research, clarity of
mechanism, few extra conditions, completeness of the answer, novelty, few new entities, decisive
experiment, silver-bullet potential), each with its reason, confidence and sources, then the
findings in the literature with quotes, open questions, limits, the search queries and the complete
abstracts that were read. `outcome` gives every hypothesis its scores (`assessment`), and the open
API `https://eternalsearch.net/api/v1/content/hypotheses/<public_id>` serves the full assessment as
JSON and as markdown in English and Russian. Tell the user where the folder is and
which index to open first. If they want another format (one file, a table, DOCX, a summary per
hypothesis), make it from these files yourself, keeping every text whole. Without the connector:
`GET <base>/runs/<run_key>/documents` and `GET <base>/runs/<run_key>/documents/file?name=<name>`
(MCP: `omega_run_documents`, `omega_run_document`, `omega_run_outcome`), no Authorization header.

- `409 run_not_done`: the server is still finishing that run's pages (`publication_pending` says
  what it still owes: titles, explanations, translations, headings). Tell the user and try again
  in a few minutes; `outcome` already shows what is published so far.
- `409 nothing_published`: the run published no question or hypothesis. Tell the user.
- `404 unknown_run`: no such run on this server; ask the user to check the key.

Only reading is open. Driving a run (status with the handoff text, pulling tasks, stop, resume,
feedback, the raw engine JSON with drafts) stays with the link that started it.

## Check that this skill is current first

You may be reading a copy saved some time ago (a file attached to a chat, a downloaded zip, an old
checkout). The server keeps the current skill and publishes the sha256 of each file at
`GET <base>/skill/version` (public, no token). Before the first run, before every resume and at the
start of every new session, check your copy:

- With the connector: `node omega-connector.mjs check-skill`. If it reports outdated files, run
  `node omega-connector.mjs update` (it downloads the current SKILL.md, connector and mcp.json over
  your copy and verifies their hashes), then **read the new SKILL.md before doing anything else**.
  `run`, `resume`, `serve`, `next` and `status` also check by themselves (at most every 10 minutes)
  and print `YOUR OMEGA POINT SKILL IS OUTDATED` when needed; `next` puts the same notice in its
  JSON as `skill_update`.
- Without the connector: compute the sha256 of each file you hold and compare with `files_sha256`;
  if you cannot compute hashes, download `<base>/skill/SKILL.md` again and use that copy.
- During a run, every pull and every status carries `skill_revision`: when it differs from the one
  you saw at the start, check again. Updating never touches a run in progress: it continues under
  the same key.
- Whenever you update, tell the user in one sentence that the skill was updated to the server's
  current version.

## Before the first run of Omega Point 1.5: ask three questions in one message (mandatory)

Ask the user, before you start the run, in their language, in ONE message, and wait for the answers.
Do not mention an option in passing ("if you like, it can be linked to your account"): the user does
not know what that means or how to do it. Ask each one as a question with its benefit and its effort:

1. **Russian versions?** Translations of every hypothesis and explanation, Russian question headings,
   a Russian report and a Russian poster sheet. (`translate_ru`, default yes)
2. **Poster sheets?** One illustrated sheet per hypothesis, English and Russian, drawn by the server.
   (`posters`, default no)
3. **Link this run to your Eternal Search account?** Then access to it can never be lost: if this
   session ends, the computer changes or the key file is deleted, any new session continues the run,
   and all your runs are listed at https://eternalsearch.net/omega/my-runs. It takes a minute: I send
   you a link, you open it and press Connect. (recommended)

For example in Russian: «Перед запуском три вопроса. 1. Нужны ли русские версии результатов: переводы
гипотез и объяснений, русский отчёт и русский постер? 2. Нужны ли постеры к гипотезам? 3. Привязать
запуск к вашему аккаунту Eternal Search? Тогда доступ к нему сохранится навсегда: если этот сеанс
закончится или вы смените компьютер, любой новый сеанс продолжит запуск, а все ваши запуски будут на
странице eternalsearch.net/omega/my-runs. Это займёт минуту: я пришлю ссылку, вы откроете её и
нажмёте «Соединить».»

Skip question 3 only when the link is already linked (`account_linked: true` in
`GET /links/current`, or `account_linked` in `~/.omega-point/link.json`).

### Linking, when the user says yes

Two calls, because your harness may show a command's output only when it ends:

```bash
node omega-connector.mjs login            # returns at once: a URL and a code (also as JSON on stdout)
# now write the user the URL, the code and the three steps; ask them to say when they have confirmed
node omega-connector.mjs login --wait     # then: waits until they confirm (up to 15 minutes), saves the token
node omega-connector.mjs runs --account   # later: every run of every agent linked to the account
```

Tell the user exactly: "Open <verification_url> and press Connect. It is a page of the Eternal Search
site in your own browser; sign in with Google there if it asks. I keep waiting and continue by myself
as soon as you have pressed it." Then run `login --wait` (it polls with `wait_s` and returns when the
user has pressed Connect) and start the run. Rules that never bend:

- **You never open the site, a sign-in page or Google yourself**, in a browser tool or otherwise, and
  you never sign in anywhere. The page is for the user, in the user's own browser.
- **You never ask the user for a password, and never ask them to type or compare the code.** The URL
  already carries the code; the page shows it only so a careful user can check it.
- **You do not ask the user to write "done".** `login --wait` (or `omega_login_poll` with `wait_s`
  25, called again and again for up to 15 minutes) returns by itself. Only if your harness cannot keep
  a command or a tool call running that long, tell the user to write one word after pressing Connect.
- The page connects the link this agent uses now (after `register`) or creates a new one. "Other
  options" on the page lets the user pick one of their links (a lost token) or decline.

What the link gives later:

- the token can never be lost for good: in a new session, on another machine, or after the token
  file was deleted, run `login` again and ask the user to choose "One of my links". The agent gets a
  NEW token for that same link (the old one stops working) and every run continues under its key;
- the user sees all their runs, where each one is, and the phrase to send the agent at
  https://eternalsearch.net/omega/my-runs.

Without the connector: `POST <base>/links/login` (body like `POST /links`; send your Bearer so the
user can bind this link), show the user `verification_url` and `user_code`, then
`POST <base>/links/login/poll {device_code}` every `interval_s` seconds until it answers 200 (MCP:
`omega_login_start`, `omega_login_poll`, `omega_account_runs`).

### Acting for the person on the site (team work, not only Omega)

When the user wants you to work on Eternal Search for their team (grant searches, projects, applications),
sign in with the site permission:

```bash
node omega-connector.mjs login --site         # the page also asks the user to allow you to act for their team
node omega-connector.mjs login --site --wait  # saves your own team key with the link (file mode 0600)
node omega-connector.mjs whoami               # link, scope, team, last four characters of the key
```

The key is yours alone: the user can revoke it at https://eternalsearch.net/account/agents without touching
their other agents or their personal key. Send it only as an `Authorization: Bearer` header to `/api/v1/*`
and to the `eternal-search` MCP server (`/api/mcp`); never put it in a URL, a tool argument, a log or a reply.
A `login` without `--site` for the same link withdraws the site permission and its key.
Web clients that cannot run commands (claude.ai, ChatGPT) never use `login --site` and never send the user a
Connect link for site work: there is no disk between chats, so a key handed to such a chat is lost with it,
and the user would be asked to connect again in every new chat. They add `https://eternalsearch.net/api/mcp`
as a connector instead, once: the first team tool answers 401 with a WWW-Authenticate challenge, the client
opens the Eternal Search sign-in and consent page (OAuth), and from then on the client itself keeps the
token (renewed for 30 days). Grant searches then go through the connector's tools `start_grant_search`,
`get_grant_search`, `list_grant_searches` and `cancel_grant_search`; `whoami` shows whom the connection acts
for. If the connector is not added, tell the user once how to add it; do not fall back to a device-code
login or ask for a key, a code or a password.

## Relay mode: when the server hands the model calls to your agent (run_mode agent_relay)

Everything from here on applies only when the start response or the status says
`run_mode: agent_relay`. Then the model calls do not go to the server's pool: every call the engine
needs comes to you as a task, you answer it with your model and post the answer back. Step 7 alone
is up to 36 calls for each of at most 10 open questions ("Step 7 is the reviewed generation").

**A relay run stops after every stage and waits for the user.** After engine steps 1, 2, 3, 4 and
6, after every 10 hypotheses of step 7, after the complete engine output, after the titles and
duplicate check, after every 10 rewritten hypotheses and after every 10 translated hypotheses, the
server holds the run's tasks. You show the user that stage's result, end your turn, and the run goes
on when the user tells you to continue. No turn of yours has to outlast a stage, so no turn dies on
a time limit in the middle of the run. See "At every checkpoint".

## At every checkpoint (mandatory)

A checkpoint is one stage result the run waits at. You see it in four places: `serve` prints
`──── STAGE RESULT: TELL THE USER NOW` and exits; `next` returns `checkpoints` with `stop_now: true`;
a pull returns a non-empty `checkpoints` with `checkpoint_instructions`; the run status carries
`checkpoint` (not null). Then, in this order:

1. Finish the answers you already hold; pull no more tasks. The server holds the rest anyway.
2. Read the checkpoint: `node omega-connector.mjs checkpoint <run_key>` (also saves it), or
   `GET <base>/runs/<run_key>/checkpoint`, or `omega_run_checkpoint`. It has `summary_markdown`, the
   overview, and `body_markdown`, the complete stage result.
3. Write the user the overview in their language as a chat message: every item with its name and
   essence, every number exactly as given. Translate; do not embellish, do not drop items.
4. Save the complete result as a file (the connector writes `omega-<run_key>/stages/NN-<stage>.md`
   and `NN-<stage>.summary.md`) and tell the user where it is. Paste it whole only when they ask;
   ten rewritten hypotheses are tens of thousands of words, never shorten them.
5. End your turn with one plain sentence that the run is paused and the exact phrase that continues
   it, for example in Russian: «Прогон остановлен после этапа и ждёт вас. Чтобы продолжить, напишите:
   продолжай».
6. Never continue on your own. When the user writes the phrase (or anything that means continue):
   `node omega-connector.mjs continue <run_key>` (`POST /runs/<run_key>/continue`,
   `omega_continue_run`), then serve again (`serve --run <run_key>`, `--detach` if you like, or the
   `next` / `answer` loop). When `continue` says the next checkpoint is already due, go back to step 2.

What the stages show: steps 1 to 6 the goal, its pillars, the requirement atoms, the research domains
with their scientific pillars and the open questions; step 7 the new hypotheses (with their
reader editions); the engine output every hypothesis under its question; then the titles with the
merged duplicates; then the rewritten hypotheses (full explanations); then the Russian translations.
The last stage is the published result: the outcome with links (see below).

A run waiting at a checkpoint waits for the user, not for you: it is kept on the server with all its
tasks for 7 days, and the 24-hour absence rule does not apply to it. After 7 days at one checkpoint it
is stopped, and `resume` continues it under the same key (a resume counts as the user's continue). The user can ask for an unattended run: start it with `--no-pauses` (`pauses: false`),
and it never stops between stages.

Long stages (step 7 can run for many hours) also stop after about 2 hours of continuous work without
a stop: a checkpoint of stage `turn_time_limit`. It carries no stage result; its `summary_markdown`
is the run's status (where it is, what is done, calls answered, how long this stretch lasted) and
what the user writes next. Treat it like any checkpoint: finish the answers in hand, write the user
the summary in their language, including the phrase to write ("continue"), save the body as a file,
and end your turn. Nothing is lost while it waits; on "continue" the run goes on where it paused.

## Step 7 is the reviewed generation

Since 2026-10-07 step 7 writes every hypothesis in stages, each a separate task in your queue: a
check of the scientific foundations, the generation itself (it receives the complete archived
abstracts the engine read), a causal map, a scientific review, a revision, a verification, then a
clarity loop (a reader edition in Russian, an independent retelling from the reader edition alone,
and an audit that sends meaning errors back to a bounded scientific revision). Every stage answers
one JSON object to an exact schema; when it does not match, the engine asks for a correction with the
contract errors listed. Up to 36 calls per open question; at most 3 questions are composed at once
(each one against the hypotheses already written). These prompts are long, because they carry the
whole source corpus: answer them with your strongest model; each such task allows 1800 s.

## Honest facts first

- **You are the proxy.** Every prompt of the engine travels to you in clear text, and your model
  writes every answer.
- **A run takes hours.** Between checkpoints your agent must keep pulling tasks. If it stops, the run
  waits (status `awaiting_user_llm`); after 24 hours of silence the run is stopped with its
  completed steps saved, and you can resume it with the same token. A resume continues the same
  run under the same key, as many times as needed.
- **Hand the user the handoff text the moment the run starts, and again after every resume.**
  Your session can end at any moment (context limit, closed terminal, crash) while the run keeps
  waiting on the server. The server therefore returns, with every started run, a paste-ready
  message called `handoff_text` (in the `POST /runs` response, in `omega_start_run`, in the run
  status, printed by the connector after `run`): the user copies it and pastes it into a new session,
  and that session finishes the run. Show it to the user **verbatim, in a code block, in your very
  next message, before you pull the first task**. Add one sentence in the user's language saying
  what it is for ("keep this; if our session ends, paste it into a new one"). Do not shorten it,
  do not rephrase it, do not replace it with the bare run key. A resume keeps the run key and
  returns the `handoff_text` again (now saying how often the run was resumed): show it the same
  way. The text looks like this:

  ```
  Finish my Omega Point run pipeline-cf15f9184116 (full run). Goal: "restore youthful skin properties in middle-aged adults".
  Read the skill first: https://eternalsearch.net/omega-point/api/agent/v1/skill (SKILL.md, section "If your session ends before the run does"). The connector script is https://eternalsearch.net/omega-point/api/agent/v1/skill/scripts/omega-connector.mjs if it is not in this directory.
  The link token is in ~/.omega-point/link.json on this machine. Do not register a new link: the run belongs to that one.
  Check that your copy of the skill is current first: node omega-connector.mjs check-skill, and if it says outdated, node omega-connector.mjs update and read the new SKILL.md.
  Keep me informed the whole time: whenever a pull returns reports_for_user, tell me its progress_report in my language at once; before you end any turn, tell me the run's progress_report from the status and the exact phrase I should send to continue. Never end a turn without a message to me.
  Your turn can end without warning, and after that you cannot write to me. So keep the run served outside your turn when you can (serve --detach below); if your harness can schedule your own next turn, schedule it before this one ends; otherwise stop each stretch before your limit and tell me plainly that your turn has ended, the run waits, and the exact phrase I should send to continue. Whatever I write next, first tell me the progress_report, then continue.
  1. node omega-connector.mjs status pipeline-cf15f9184116 and read relay_phase.
  2. relay_phase engine or finishing: node omega-connector.mjs serve --run pipeline-cf15f9184116 --detach (serves in the background, independent of this session, until relay_phase is done; a link registered with --provider subagent: the next / answer loop instead, in stretches as above). Do not stop the run and do not resume it.
  3. relay_phase stopped and resumable true: node omega-connector.mjs resume pipeline-cf15f9184116. The run keeps this same key: a lost engine continues from its saved steps, a stopped finishing phase is revived; then serve --run pipeline-cf15f9184116 again. Exception: when the status says the engine stopped the run on purpose (error_message begins "stopped before step 3"), do not resume it; tell me the reason and propose a clearer wording of my question.
  4. relay_phase done: node omega-connector.mjs outcome pipeline-cf15f9184116. Give me the links to every published question and hypothesis (English and Russian), say how large the texts are, offer to paste them into the chat in the format I ask (node omega-connector.mjs outcome pipeline-cf15f9184116 --texts carries the full texts), and ask me for feedback.
  Through the MCP server instead of the connector: omega_run_status, then omega_pull_task and omega_complete_task, omega_resume_run or omega_run_outcome, the same way.
  ```
- **Keep the user informed the whole time. This is mandatory.** A run takes hours, and the user
  sees only what you write in the chat: an agent that speaks at the start and at the end leaves
  them looking at a silent chat for hours, unable to tell a working run from a hung one. The server
  writes the report for you: every run status carries `progress_report`, a short paragraph for the
  user (phase, step, what is still owed by stage, calls answered, time since the start, whether the
  run waits for an agent, what comes next), and a pull carries `reports_for_user` whenever a report
  is due (a stage changed, or 10 minutes passed). The rules:
  1. Whenever a pull returns a non-empty `reports_for_user` (the connector prints it between
     `──── TELL THE USER NOW` rules, and `next` puts it in its JSON), send the user a chat message
     with that `progress_report` at once, in the user's language, before you answer more tasks.
     Keep its numbers exactly; translate, do not embellish.
  2. Before you end any turn, for whatever reason (a turn limit, a context limit, an error, a pause),
     read the status (`node omega-connector.mjs progress <run_key>`, `GET /runs/{key}`,
     `omega_run_status`) and write the user its `progress_report`, then what happens next and the
     exact phrase they should send to continue (for example: "continue"; or the handoff text if this
     session cannot go on). Never end a turn with no message to the user.
  3. How a turn may end is set by the next point, "When your turn can end": read it before you serve.
  4. If something stops you (no network, a provider error, quota), tell the user what failed and how
     to continue, the same way. A run waiting for your agent is safe on the server for 24 hours.
     **Network blocked by your own sandbox** (the call to eternalsearch.net never leaves your
     environment): name the exact remedy instead of stopping. Codex cloud: in the environment
     settings turn "Agent internet access" on, add the domain `eternalsearch.net` to the allowlist
     and allow all HTTP methods (the relay uses POST), then start the task again. Any web chat: add
     the MCP server https://eternalsearch.net/api/mcp/omega-agent as a connector, then the calls
     leave through the connector and your sandbox is not involved. Never try to reach the site
     through a browser tool instead: the site is not an interface for agents.
- **When your turn can end: continue by yourself, or say so plainly. This is mandatory.** Your
  harness can stop you without warning (a turn time limit, a step limit, a context limit, a closed
  chat), and once it has, you cannot write a single word more: the user sees a chat that simply went
  quiet, and the run waits for an agent that is gone. Hosted agents and web chats have ended turns
  after 3.5 and 6.5 hours of a run with no message at all. The message must therefore be written
  BEFORE the cut, and wherever possible the run must not depend on your turn at all. In this order:
  0. **With checkpoints (the default) your turn ends at every stage anyway**: serve until the
     checkpoint, show it, end the turn (see "At every checkpoint"). The rules below matter inside a
     long stage and for runs started with `--no-pauses`.
  1. **Keep the run served outside your turn.** With the connector and a CLI or API provider
     (Route A) start the serve in the background: `node omega-connector.mjs serve --run <run_key>
     --detach`. It runs as its own process, independent of your session, logs to
     `~/.omega-point/serve-<run_key>.log`, stops by itself when the run owes nothing more, and refuses
     to start a second copy. Then the end of a turn costs nothing: tell the user the serve runs in
     the background, and on every later turn read `node omega-connector.mjs progress <run_key>` and
     tell them the report. Use the plain (foreground) `serve` only when you will watch it to the end.
  2. **Bring yourself back.** If your harness can start your next turn by itself (a loop or wake-up
     command, a scheduled task, a background job that re-invokes you, an automation), schedule your
     next turn before this one ends, with the instruction "continue serving Omega Point run
     <run_key>: read its status, tell the user the progress_report, serve until relay_phase is
     done". Tell the user that you scheduled it and when it fires. This matters most in subagent
     mode (Route B) and over MCP (Route C), where you answer the tasks yourself and nothing serves
     while you are stopped.
  3. **Otherwise stop before the limit, and say so.** Serve in stretches shorter than your limit:
     about two thirds of it if you know it, at most 30 minutes if you do not. End every stretch with
     the message of rule 2 of "Keep the user informed" and one plain sentence in the user's language that your turn has
     ended, the run is waiting for you, and the exact phrase that continues it, for example in
     Russian: «Мой ход закончился, прогон ждёт. Чтобы я продолжил, напишите: продолжай». If this
     session cannot go on at all (the context is nearly full), give the handoff text instead.
  4. **Whatever the user writes after a pause, start with the run.** Read the status, tell them its
     `progress_report`, then continue serving (or check that the background serve is still running:
     `serve --run <run_key> --detach` again starts one only if none is alive).
- **The run goes as fast as your agent: the server never caps your width.** A run is a graph of
  units of work, and the server knows which are independent (`GET <base>/parallelism` lists them:
  the pillars of step 3, the domains of step 4b, the review batches of steps 2, 6 and 7, and after the engine
  every title, claim, explanation, heading, gloss, audit and translation of the run). It issues
  every ready unit at once and queues them for you in priority lanes: lane 0 is the engine, then
  the finishing stages in the order that unlocks the most work (titles before explanations, before
  headings, before translations). Your pull always gets the highest lane first. So answer as many
  tasks at once as you can: one subagent per task, as many subagents as your harness and your
  subscription allow. Every pull shows `waiting_by_lane`, the work ready for you right now.
  Two narrower spots are deliberate and stated in `/parallelism`: step 7 composes gaps a few at a
  time against the hypotheses already written (the ledger), and a few engine steps are a chain.
- **Declare the width you really have.** The link's `concurrency` (1..256) is how many tasks the
  server keeps in flight for you. A Codex login serves 4 at once well (Eternal Search runs five per
  login in production), an API key 4 or more, a Claude Code login 1 (its credential file can race
  on a token refresh; raise it knowingly with `--concurrency`, and the connector drops back to 1 on
  the first auth error). Several logins on one machine add up: `--codex-home a,b,c` registers
  three, each call goes to the least-loaded one, and the default width is 4 × 3. With subagents,
  pull several tasks at once (`next --max N`, `omega_pull_task` with `max_tasks`) and answer them in
  parallel. The width can change at any moment (`set-concurrency N`, `serve --concurrency N`,
  `omega_set_concurrency`, `PATCH /links/current`): the next pull and the run's next fan-out follow.
- **The token is the only key.** Registration is anonymous and open; the token is shown once.
  Lose it and that link's runs stay stored but unreachable to you.
- **Tiers, not model names.** Each task says `tier: high | mid | low`. You decide which of your
  models answers each tier. Use your strongest model for `high`.
- **JSON answers.** When a task carries `response_format: {"type": "json_object"}`, answer with
  one JSON object and nothing else. The engine asks once for a correction if parsing fails.
- **Every run is a full run.** There is no trial mode: `POST /runs` does not take a `test_mode`
  flag, and a run started through it goes through the same steps, selection and finishing stages
  as a run started on the public site. Expect the full several hundred calls from the first run.
- **The run is not over when the engine is.** A run goes the same way as one started on the
  public site: the engine reasons to the hypotheses of step 7, then the server names each
  hypothesis, removes duplicates, writes the explanations and question headings, translates,
  and writes the Russian report. Every one of those calls comes to you too, through the same
  queue. The engine's own status turns to `completed_at_step` at that point: **that is not the
  end.** Keep serving until the run's `relay_phase` is `done` (or `stopped`); `keep_serving`
  in the status says the same in one word, `finishing_pending` counts what each stage still
  owes, and `next_action` says in one sentence what to do. `GET /runs/{key}/result` answers 202
  until the phase is `done`. Do not call `stop` on a run whose engine has finished: on such a
  run `stop` ends the finishing phase, and the hypotheses stay without titles, explanations and
  translations on both sides. The connector's `serve --run` handles all of this by itself.
- **The goal is the user's question, in the user's own words and language.** Pass what the user
  asked, as they wrote it: «хочу найти новые гипотезы в сфере меметиков; предложи самые
  перспективные эксперименты и теории» goes in as exactly that. Do not expand it into a brief.
  Do not add how many hypotheses or families to return, ranking criteria, a template for each item,
  methods or disciplines to use, evidence standards, or what to hand back (pages, files,
  translations, posters): the engine decides all of that itself, and when such instructions arrive
  inside the goal it builds its decomposition out of your checklist instead of the user's subject.
  Russian versions and posters are set with `translate_ru` and `posters`, never in the goal. If the
  question is unclear, ask the user and agree a wording with them before starting; then pass the
  wording they agreed to. The engine sets aside instruction-like text it finds in a goal, but it can
  only work from what the user actually asked if you send it.
- **The engine stays on the subject of the question.** It produces hypotheses, rival theories and
  experiments for every question, so "find new hypotheses about X" is a question about X itself:
  the engine studies how X works, never how to rank or count hypotheses about X. Step 0 records the
  subject; every stage receives it; at steps 2, 6 and 7 a review removes pillars, gap questions and
  hypotheses that are about something else (the research method, a ranking of hypotheses, another
  phenomenon). These reviews are ordinary tasks in your queue, answered like any other.
- **A run can stop on purpose after step 2.** When no goal pillar carries the kind of answer the
  question asks for, or none of them is about its subject, even after one retry, the engine stops
  the run before step 3 instead of spending hours on a different question. The status is then
  `interrupted_at_step`, `error_message` begins with "stopped before step 3" and states the reason,
  and `next_action` says so. Tell the user that reason in their language and propose a clearer
  wording of their question; start a new run with the wording they agree. Do not resume such a run
  on your own: resuming is the user's decision (with a missing answer type it proceeds with the
  saved pillars; with a lost subject it recomputes step 2).
- **Ask about Russian before starting.** Russian versions (translations, Russian headings, the
  Russian report, the Russian poster sheet) are the user's choice. Ask the
  user, then pass `translate_ru: false` to skip them or leave the default `true`.
- **Ask about posters before starting.** Poster sheets (one per hypothesis, English and Russian)
  are the user's choice too. Ask the user, then pass `posters: true` to produce them; the default is
  `false` (no posters).
- **Ask about linking the account before starting.** In the same message as Russian and posters
  (see "Before the first run: ask three questions"): a run linked to the user's account can always be
  continued and is listed on their runs page. If they say yes, run `login` before `run`.
- **One thing your model does not do: poster images.** Poster sheets are drawn by the server's
  image generation; a text model cannot draw them. Everything else, text included, is yours.
- **When the run is done, hand the user the published result as links.** A finished run is
  published on the site: one page per open question (`/questions/open/<public_id>`, Russian at
  `/ru/questions/open/<public_id>`) and one per hypothesis under it (`/omega/hypothesis/<public_id>`,
  Russian at `/ru/...`). A run can publish several questions. `GET /runs/{key}/outcome`
  (`node omega-connector.mjs outcome <run_key>`, `omega_run_outcome`) lists them all with both
  language URLs, the heading of each question in English and Russian, the published hypotheses
  under it, and the size of every text counted from what is stored (words and characters, English
  and Russian separately, with run totals). Show the user the links first, one line per question
  and its hypotheses under it; then state the total size of the texts; then offer to paste the
  texts into the chat in the format they ask (whole, per question, per hypothesis, a summary, a
  table). `?texts=true` (`outcome <run_key> --texts`, `texts: true`) carries the full stored texts
  for that. Never shorten a text you paste; a whole hypothesis page is several thousand words, so
  say so and let the user choose. The raw engine JSON (`result`) stays available, but it is not
  what the user should be shown.
- **Then save the run as files and tell the user where they are.** Once `relay_phase` is `done`,
  the server hands out the run as a folder: one markdown file per published open question and per
  published hypothesis, per language (`questions/<id>.en.md`, `hypotheses/<id>.ru.md`), each with
  the text and structure of its page on the site; an index per language (`index.en.md`,
  `index.ru.md`) linking every file; and the poster sheets as the original PNG files
  (`posters/<id>.<lang>.png`), which the documents show as their images. Forty published hypotheses
  give forty files per language. Only what the site publishes is in it: no drafts, no merged or
  archived hypotheses. `node omega-connector.mjs documents <run_key>` writes the whole folder
  (`--dir` to choose where); through the API or MCP, `GET /runs/{key}/documents`
  (`omega_run_documents`) lists the files and `GET /runs/{key}/documents/file?name=<name>`
  (`omega_run_document`) returns one markdown file per call. Save every file under its name, in
  full; the links and images inside are relative to that layout. Before `done` the server answers
  409 `run_not_done`.
- **After the run, ask the user for feedback and store it.** When `relay_phase` is `done`, show
  the user the outcome and ask what is wrong, missing or worth improving. Post their remarks with
  `POST /runs/{key}/feedback` as `author: user, kind: feedback`, and the concrete corrections or
  improvements you formulate from them as `author: agent, kind: proposal` (a proposal can point at
  one hypothesis by its public id, one explanation, one question or one stage). The entries are
  stored per run and read by the Eternal Search operator on the runs desk; nothing is applied
  automatically. Feedback on a stopped or failed run is welcome too. Tell the user this
  possibility exists even if they have nothing to say.
- **A 502 or a reset connection means the server is restarting.** New code ships several
  times a day and the relay is down for a few seconds each time; the 502 body is Cloudflare's
  HTML page, not JSON. The connector script and the MCP server wait this out for you (retries
  with growing pauses, about three minutes in total). If you call the API yourself (Route B),
  do the same: wait 15 seconds and repeat the same call. Nothing is lost: a link, a run and a
  leased task all live in storage that survives the restart, and a run whose agent stays
  silent is parked, not failed (`awaiting_user_llm`), until you pull again.

## Route A: the connector script (recommended), relay mode

`scripts/omega-connector.mjs` needs Node 20+ and nothing else. Fetch it from
`<base>/skill/scripts/omega-connector.mjs` or use this package. (For a server run the same script
registers, starts and follows the run: see "A run on the server".)

1. Register a link with the provider you will answer with:

   ```bash
   node omega-connector.mjs register --provider codex        # your Codex subscription login, concurrency 4
   node omega-connector.mjs register --provider codex --codex-home ~/.codex-a,~/.codex-b   # two logins, concurrency 8
   node omega-connector.mjs register --provider claude       # your Claude Code login, concurrency 1
   node omega-connector.mjs register --provider openai-key   # OPENAI_API_KEY, concurrency 4
   node omega-connector.mjs register --provider base-url --base-url https://host/v1 --key K
   ```
   Options: `--high/--mid/--low <model>` to set the tier map, `--concurrency N` (1..256, how many
   tasks you answer at once; the engine fans out that wide), `--label "..."`.
   The token is saved to `~/.omega-point/link.json` (mode 600).

2. Ask the three questions of "Before the first run" in one message (Russian versions, poster
   sheets, linking the account) and wait for the answers. If the user wants the account link, run
   `login`, give them the URL and the code, then `login --wait`. Then start the run with the user's
   question in their own words as the goal (see "The goal is the user's question" above); add
   `--no-russian` if they declined Russian versions and `--posters` if they requested poster sheets:

   ```bash
   node omega-connector.mjs run "restore youthful skin properties in middle-aged adults"
   node omega-connector.mjs run "<goal>" --no-russian
   node omega-connector.mjs run "<goal>" --posters
   node omega-connector.mjs run "<goal>" --no-pauses               # only if the user asks for an unattended run
   ```
   `run` prints the handoff text between two `────` rules. Show it to the user verbatim now,
   before serving: they paste it into a new session if this one ends.

3. Serve the run until its `relay_phase` is `done`. Keep this process alive the whole time,
   including after the engine has finished (titles, dedup, explanations, translations and
   headings come afterwards):

   ```bash
   node omega-connector.mjs serve --run <run_key> --detach          # recommended: in the background, survives your session
   node omega-connector.mjs serve --run <run_key>
   node omega-connector.mjs serve --run <run_key> --concurrency 4   # widen or narrow the link first
   ```
   With `--detach` the serve prints its pid and its log file and keeps running after your turn or
   session ends; the progress reports go to that log, so read `progress <run_key>` on every turn
   and tell the user (see "When your turn can end").
   At a checkpoint `serve` finishes the answers in hand, saves the stage result, prints it between
   `──── STAGE RESULT: TELL THE USER NOW` rules and exits (a detached serve too: its log has it, and
   `checkpoint <run_key>` shows it again). Follow "At every checkpoint"; after the user's continue:

   ```bash
   node omega-connector.mjs checkpoint <run_key>                   # the stage result the run waits at (overview + file)
   node omega-connector.mjs continue <run_key>                     # ONLY on the user's word; then serve again
   node omega-connector.mjs checkpoint <run_key> --seq 3           # an earlier stage result again
   ```
   `serve` pulls tasks (long poll, 25 s), answers up to `concurrency` of them at once with your
   provider, validates JSON when asked, posts the answers, logs every task with its tier, size
   and duration, and exits by itself when the run owes nothing more. Ctrl-C releases in-flight
   tasks back to the queue so nothing is lost. `set-concurrency N` changes the width of a link
   at any time, also while a run is executing. When a progress report is due, `serve` prints it
   on stderr between `──── TELL THE USER NOW` rules: watch its output and tell the user each one
   in the chat while it keeps serving.

4. Hand the user the outcome: `outcome` prints the links to every published question and
   hypothesis (English and Russian), the size of each text and the totals; relay that list, then
   offer to paste the texts into the chat in the format the user asks (`--texts` carries them, in
   full). The raw engine JSON is still there as `result` (202 with `next_action` while the run
   still owes calls; `--engine-only` reads it early on purpose), but the links are what the user
   should get. Then save the documents folder with `documents <run_key>` and tell the user its
   path (the command prints it; `index.ru.md` or `index.en.md` is the file to open first):

   ```bash
   node omega-connector.mjs status <run_key>
   node omega-connector.mjs progress <run_key>                     # the progress report to tell the user now
   node omega-connector.mjs outcome <run_key>                      # links + sizes, readable on stderr, JSON on stdout
   node omega-connector.mjs outcome <run_key> --texts --out texts.json   # the full texts, for pasting in any format
   node omega-connector.mjs documents <run_key>                    # the folder: index, one .md per question and hypothesis, poster PNGs
   node omega-connector.mjs result <run_key> --out result.json     # raw engine result
   node omega-connector.mjs runs | stop <run_key> | resume <run_key>
   ```

5. Ask the user for feedback and store it, with the corrections or improvements you propose:

   ```bash
   node omega-connector.mjs feedback <run_key> --author user --kind feedback --file user-note.txt
   node omega-connector.mjs feedback <run_key> --author agent --kind proposal --target hypothesis:<public_id> --file proposal.txt
   node omega-connector.mjs feedback-list <run_key>
   ```

## Route B: subagent mode (no CLI login to reuse), relay mode

Your harness answers each task itself, with a fresh subagent per task, while the script only
keeps the state:

```bash
node omega-connector.mjs register --provider subagent --kind claude_code
# ask the three questions of "Before the first run"; if the user wants the account link:
node omega-connector.mjs login                 # returns at once: tell the user the URL and the code
node omega-connector.mjs login --wait          # after that: waits for their confirmation
node omega-connector.mjs run "<goal>"          # prints the handoff text: show it to the user verbatim before the first pull
node omega-connector.mjs next --max 4         # prints up to 4 tasks {task_id, tier, messages, response_format, timeout_s}
# answer them IN PARALLEL, one fresh subagent per task, the strongest model you have for its tier; one file each
node omega-connector.mjs answer <task_id> --file answer.txt
```

When the JSON printed by `next` carries `reports_for_user`, tell the user each `progress_report` in
the chat first (see "Keep the user informed"), then answer the tasks. When it carries `checkpoints`
and `stop_now: true`, answer only the tasks you already hold, then follow "At every checkpoint"
(the connector has already saved the stage result and printed the overview). In this mode nothing serves
the run while your turn is stopped: schedule your own next turn if your harness can, or serve in
stretches and end each one as "When your turn can end" says.
`next --max N` pulls up to N tasks and widens the link to N when it is narrower, so the engine
issues that many at once; run one subagent per task at the same time rather than one after the
other, and post each answer as soon as it is ready. Plain `next` prints one task. Loop `next` /
`answer` until `status` shows `relay_phase: done` (or `stopped`); `keep_serving` false means the
same. Answer within `timeout_s` seconds of pulling, or the engine re-issues the task. When `next` returns `task: null`, the server is doing work that needs no model (literature
search, storage, the wait for the next stage); call `next` again. A status of `completed_at_step`
with `relay_phase: finishing` means the engine is done and the finishing stages are still sending
tasks: keep looping. Pass `--no-russian` when the user does not want Russian versions and
`--posters` when they request poster sheets. When the phase is `done`, run `outcome`: give the user the
links and the text sizes, offer the texts in the format they ask (`outcome <run_key> --texts`), then
save the folder with `documents <run_key>` and tell the user where it is, then ask for feedback and
store it with `feedback` (see steps 4 and 5 of Route A).

## Route C: remote MCP, no script at all (both modes)

Add the Eternal Search MCP server and use its tools in the same loop:

```bash
claude mcp add --transport http omega-point https://eternalsearch.net/api/mcp/omega-agent \
  --header "Authorization: Bearer <token>"
```

Tools: `omega_register` (no token needed; returns the token once), `omega_set_concurrency`,
`omega_start_run`, `omega_pull_task` (`max_tasks` up to your concurrency; answer the tasks in
parallel subagents), `omega_complete_task`, `omega_run_status`, `omega_run_outcome` (links,
sizes; `texts: true` for the full texts), `omega_run_documents` and `omega_run_document` (the
folder of markdown files and poster PNGs, one file per call), `omega_run_result` (raw engine JSON), `omega_stop_run`,
`omega_resume_run`, `omega_submit_feedback`, `omega_list_feedback`, `omega_run_checkpoint` and
`omega_continue_run` (checkpoints: see "At every checkpoint"; `omega_start_run` takes `pauses`). `mcp.json`
in this package is a ready configuration.
`omega_start_run` and `omega_resume_run` return `handoff_text` next to the `run_key`: show it to the
user verbatim at once, before the first `omega_pull_task`.
When `omega_pull_task` returns a non-empty `reports_for_user`, tell the user each `progress_report` in
the chat at once; before ending a turn, read `omega_run_status` and tell them its `progress_report`.

## If your session ends before the run does

The run lives on the server, not in your session. The user opens a new session and pastes the
handoff text above; it names the run key and says what to do. Do not start a new run: finish this
one. If the user has only the run key, or nothing, `node omega-connector.mjs runs` lists the link's
runs and `last_run` in `~/.omega-point/link.json` is the most recent one; that file also holds the
token, so this works on the machine where the link was registered. On another machine, or when the
token is missing or rejected (401), do not register a new link (the run belongs to the old one): run
`node omega-connector.mjs login` and ask the user to choose "One of my links" with that link; the agent
receives a new token for it and continues the same run key. This works when the link was linked to
the user's account; for an anonymous link only its original token reaches it.
This paragraph is about Omega runs and the link token. It never applies to site work (grant searches,
projects): a web client does that through the `eternal-search` connector signed in once by OAuth (see
"Acting for the person on the site"), so a missing site key in a new chat is never a reason to run
`login --site` or to send a Connect link.

1. **Read the status:** `node omega-connector.mjs status <run_key>` (`GET /runs/{key}`,
   `omega_run_status`). `relay_phase` and `next_action` say what to do:
   - `checkpoint` is not null: the run waits for the user at a stage result. Show it ("At every
     checkpoint") and end the turn; continue only on the user's word.
   - `engine` or `finishing` (`keep_serving: true`; status `executing`, `awaiting_user_llm` or
     `completed_at_step`): the run is waiting for you. Serve it again exactly as before: `serve --run
     <run_key> --detach` (Route A; it starts nothing if a background serve is still alive), the `next` / `answer` loop (Route B), `omega_pull_task` (Route C). Tasks
     whose answers never came back are re-issued by the engine; nothing is lost and nothing needs
     resuming. Do not call `resume` on such a run.
   - `stopped` and `error_message` begins with "stopped before step 3": the engine stopped the run
     on purpose (see "A run can stop on purpose after step 2"). Tell the user the reason and propose
     a clearer wording; resume only if the user asks for it.
   - `stopped` with `resumable: true`: `node omega-connector.mjs resume <run_key>`
     (`POST /runs/{key}/resume`, `omega_resume_run`). The run continues **under the same key**.
     A lost engine (status `stopped_awaiting_user_llm` after 24 h without an agent, or
     `interrupted_at_step`) continues from its saved steps (the step it died in is redone from its
     start); `resume_count` in the status counts the restarts. A run whose engine had finished but
     whose finishing phase was stopped (status `completed_at_step`, someone called `stop` while
     titles, explanations or translations were still owed) is revived: the phase goes back to
     `finishing` and the same stage rows are served again, nothing is recomputed. Either way show
     the returned `handoff_text` to the user again, then serve the same key.
   - `done`: nothing more will come. Hand the user the outcome (links, sizes, texts on request),
     save the documents folder (`documents <run_key>`) and ask for feedback (steps 4 and 5 of Route A).
   - `stopped` with `resumable: false`: the run cannot continue (it failed without saved steps).
     Tell the user, offer to store feedback, and start a new run only if they ask for one.
2. **Serve to the end again:** `relay_phase: done`, then the outcome, then feedback.
3. **Show the handoff text again** when the user asks for it or when you expect to run out of
   context: it is in every status response (`handoff_text`), so you never need to recompose it.

## The wire protocol in one screen

All calls are JSON; every call except registration and reading a run's published results (`outcome`, `documents`) sends `Authorization: Bearer <token>`.

| Call | Purpose |
|---|---|
| `POST /links` | `{agent_kind, provider_label, tier_models, concurrency}` → `{link_id, token}` once |
| `POST /links/login`, `/links/login/poll` | device-code login to the user's site account: `{device_code, user_code, verification_url, interval_s}`, then poll → 202 waiting, 200 `{token, link_id, rotated}` (a token null = this link is now linked and keeps its token), 410 declined or expired |
| `GET /account/runs` | every run of every link of the account (the link must be account-linked) and `runs_page` |
| `PATCH /links/current` | `{concurrency}` (1..256): how many tasks you answer at once; the next pull and the run's next fan-out follow |
| `GET /skill/version` | public: the current skill `revision`, the sha256 of every skill file and where to download each; compare your copy before a run, a resume and a new session |
| `GET /parallelism` | public: which units of a run are independent, the barriers with their reasons, and the priority lanes |
| `POST /runs` | `{goal, global_lens?, translate_ru?, posters?, pauses?}` → `{run_key, run_mode, handoff_text, queued_position?}`; always a full run (no trial mode); `run_mode` server: the server executes it, up to three runs per person at a time, queued when the pool is full, `pauses` ignored; `run_mode` agent_relay: `pauses` default true, a checkpoint after every stage; `goal` is the user's question in their own words, never a brief; `translate_ru` defaults to true and `posters` defaults to false; show `handoff_text` to the user verbatim |
| `POST /tasks/pull` | `{max_tasks ≤ concurrency, wait_s ≤ 25}` → `{tasks: [{task_id, run_key, tier, effort?, messages, response_format, temperature, max_tokens, timeout_s, attempt}], queue_depth, in_flight, waiting_by_lane, reports_for_user: [{run_key, reason, relay_phase, progress_report}], checkpoints: [{run_key, seq, stage, title}], checkpoint_instructions}`; `effort` is the optional low, medium or high reasoning hint; highest-priority lane first; the pull is your heartbeat; tell the user every report in `reports_for_user` at once |
| `POST /tasks/{id}/complete` | `{content, model?, usage?}` or `{error: {kind, message}}` |
| `POST /tasks/{id}/release` | give a pulled task back untouched |
| `GET /runs/{key}` | status, step, `run_mode` (server or agent_relay), `relay_phase`, `keep_serving` (always false for a server run), `finishing_pending`, `next_action`, `progress_report` (for the user), `handoff_text`, `resumable`, `translate_ru`, `posters`, `feedback_count`, counters, `awaiting_since`, `queue_depth`, `agent_present` |
| `GET /runs/{key}/outcome` | open to anyone, any run, no token: what the run published, for the user: per open question its English and Russian page URLs and headings, the published hypotheses under it with their URLs, the size of every text (words and characters, counted) and run totals; `?texts=true` adds the full texts; `complete: false` while finishing |
| `GET /runs/{key}/documents` | open to anyone, any run, no token, once the run's pages are final (`publication` finished or stopped): the run as a folder; every file name (its relative path), kind (index, question, hypothesis, poster), language, page URL, and for posters the `image_url` of the PNG; the index texts; 409 `run_not_done` before |
| `GET /runs/{key}/documents/file?name=<name>` | one markdown file of that folder in full (`content`, `chars`, `words`); for a poster, its `image_url` |
| `GET /runs/{key}/result` | the raw engine result JSON once `relay_phase` is `done`; 202 while the engine runs or the finishing stages still serve (`?engine_only=true` reads the engine result early) |
| `GET /runs/{key}/checkpoint` | the stage result the run waits at: `summary_markdown` (the overview for the chat), `body_markdown` (the complete result, a file); 404 `no_checkpoint` when not paused. `/checkpoints` lists all, `/checkpoints/{seq}` one |
| `POST /runs/{key}/continue` | only on the user's word: release the checkpoint; held tasks go back; names the next checkpoint when it is already due |
| `POST /runs/{key}/stop`, `/resume` | stop (on a run whose engine is done: ends the finishing phase); continue a lost or parked run under the same key from its saved steps, repeatable → `{run_key (same), resume_count, handoff_text}` |
| `POST /runs/{key}/feedback` | `{entries: [{author: user\|agent, kind: feedback\|proposal, target_kind?, target_id?, body}]}` → stored rows; any run status |
| `GET /runs/{key}/feedback` | the stored feedback and proposals with their disposition |

Run statuses: `queued_for_slot` (server run waiting for a free slot), `executing`,
`awaiting_user_llm` (relay: tasks waiting, nobody pulling for 60 s), `completed`,
`completed_at_step`, `interrupted_at_step`, `failed_at_execute`, `stopped_awaiting_user_llm`
(relay: 24 h without you; resumable under the same key). The engine status alone ends too
early: `relay_phase` is `engine` while the engine runs, `finishing` while titles, dedup,
explanations, translations and headings are still written, `done` when nothing more will come,
`stopped` when the run ended without finishing. In relay mode, serve while `keep_serving` is true.

## What stays on the server

Literature search (PubMed, OpenAlex, Semantic Scholar), embedding-based deduplication,
validation, state and storage, and, for a server run, every model call. Every run is stored in
the Eternal Search database and published on the site when it finishes.
