Install any skill in seconds. Free to start, no credit card required.
Get Started Free →MCP-owned Ralph loop around background evolve_step jobs
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 91% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 87% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 146% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 41% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 58% | 0% |
MCP-owned Ralph loop around background evolve_step jobs. "The boulder never stops."
ooo ralph --lineage-id <lineage_id>
/ouroboros:ralph --lineage-id <lineage_id>
# For a plain natural-language request, run `ooo interview` + `ooo seed` first,
# then call the MCP tool with a fresh lineage_id and the validated Seed YAML.Trigger keywords: "ralph", "don't stop", "must complete", "until it works", "keep going"
Ralph is owned by the ouroboros_ralph MCP tool. In non-plugin runtimes, the tool starts one background Ralph job, runs repeated evolve_step generations inside that job, and stops only when QA passes, convergence is reached, a terminal evolution action occurs, cancellation is requested, or max_generations is reached. In OpenCode plugin mode, the MCP tool returns a delegated_to_plugin envelope with job_id=None; the bridge plugin dispatches a child Task session that owns the loop instead of creating a local JobManager job.
The client skill should not reimplement the loop. Deterministic frontmatter dispatch is limited to the router's named --lineage-id option so raw trailing text is never treated as lineage identity. Raw natural-language ooo ralph "<request>" input must flow through the validated Seed path before any mutating Ralph loop starts. Until a lineage id and optional Seed YAML are prepared, ouroboros_ralph returns structured input guidance instead of starting a job. Once the inputs are prepared, start the MCP-owned Ralph surface once, then follow either the returned job tools path or the OpenCode Task widget path.
When the user invokes this skill:
The Ouroboros MCP tools are often registered as deferred tools that must be explicitly loaded before use. Do this before preparing input or calling Ralph:
tool discovery query: "+ouroboros ralph job"
mcp__plugin_ouroboros_ouroboros__ouroboros_ralph. Use the actual tool names returned by runtime tool discovery; the bare names below are the canonical MCP tool names for documentation.
ouroboros_ralph and the job tools (ouroboros_job_wait,ouroboros_job_status, ouroboros_job_result, and ouroboros_cancel_job) are callable. If the tools are unavailable, stop and tell the user that Ralph requires the Ouroboros MCP runtime.
lineage_id and explicitly wants tocontinue it, reuse that lineage_id and omit seed_content unless they explicitly provide an updated Seed.
seed_content and generate a fresh lineage_id for this run. Keep lineage_id separate from Seed, interview, and session IDs so separate Ralph runs over the same Seed do not collide.
it as a direct ooo ralph "<request>" command, do not freehand Seed YAML, and do not pass raw text as seed_content. Route through the authoritative Seed path first: ooo interview to capture requirements, then ooo seed / ouroboros_generate_seed to produce validated Seed YAML with the normal ambiguity gate. After Seed generation, call the MCP tool with a fresh lineage_id and that validated Seed YAML as seed_content; do not use the raw request text. If an interview/seed session already exists in context, reuse that validated Seed output instead of regenerating it.
ouroboros_ralph with:lineage_id: existing lineage id for an explicit continuation, otherwise afreshly generated stable id for this Ralph run, such as ralph-<short-slug>-<uuid>; do not use a Seed/interview id by itself
seed_content: valid Seed YAML for generation 1 when starting a new lineageexecute: default trueparallel: default trueskip_qa: default falseproject_dir: explicit target project directory when knownmax_generations: default 10 unless the user requests a tighter boundresponse.meta.job_id is present, report it concisely and retain thejob cursor from response.meta.cursor:
[Ralph] Started background loop: <job_id> Lineage: <lineage_id> Live view: <response.meta.dashboard_url, or ouroboros tui open>
A read-only observer will report meaningful progress, attention, and terminal events here. This conversation remains available for other safe work.
response.meta.job_observer is unavailable, recover it from the final<!-- ouroboros-job-observer-v1 base64 ... --> content sentinel. Fail closed unless the single bounded payload passes canonical v1 validation and its job identity matches the visible start receipt. Visible IDs are identity anchors only; never reconstruct tools or arguments from them.
job_observer is present and thehost supports an independent Task/Agent child, spawn exactly one read-only observer and pass the contract unchanged. It owns wait/result and the cursor exclusively. The main session must not poll the same job. Keep the conversation available for read-only review, explicit control, or unrelated work in an isolated worktree; check active-worker overlap before writing to Ralph's workspace. Do not claim an observer until Task/Agent returns a live child handle. If child creation succeeds on Codex, keep the parent turn open with wait_agent calls of at most 60 seconds until the observer returns its terminal summary. Child send_message calls only queue mailbox events and cannot revive an ended parent turn. Relay meaningful updates, handle user input if it interrupts the wait, and resume waiting while the observer is active unless the user asks to stop live observation or replaces the active request. Then end only the relay loop, keep the durable job running, and offer next-turn or explicit-status catch-up. If the observer child fails, is cancelled, or exits before a terminal summary, use that same fallback instead of waiting indefinitely. This relay loop must not poll the job or take cursor ownership. If child creation fails, do not promise live proactive relays. The detached worker survives the stdio turn; catch up from durable events on the next parent turn or explicit status request. Keep the fallback polling loop open only for explicit live watching.
response.meta.status == "delegated_to_plugin" andresponse.meta.job_id is None, report that OpenCode plugin mode delegated the loop to a child Task session. Do not call ouroboros_job_wait, ouroboros_job_result, or ouroboros_cancel_job without a job id; follow the host Task widget/session lifecycle instead.
job_id exists.The delegated observer is the default owner. Use the main-session loop only when no independent child exists and the user asked for live watching; otherwise catch up on the next parent turn. Never run both:
ouroboros_job_wait(job_id, cursor, timeout_seconds=120, stream="linked", wait_for="attention_or_ac_change") for long polling;after every wait/status response, update cursor = response.meta.cursor
ouroboros_job_status(job_id) for a quick status checkouroboros_job_result(job_id) when the job is terminalouroboros_cancel_job(job_id) if the user says stop/cancelRelay Synapse queued, applied, completed, rejected, and delivery_uncertain states in the user's current conversation language. Never describe queued as applied, and surface rejected or uncertain delivery immediately. Also relay run configuration, total ACs and dependency/parallel levels, first scheduled ACs, bounded Discover targets, material model/harness changes, level transitions, and verified AC completion. Never expose raw commands or model reasoning.
For a live AC question or additive refinement, reload +ouroboros session signal, call ouroboros_session_signal_targets, and semantically select the relevant AC without asking for internal IDs. Use mode="inform" for read-only assurance and omit fallback_mode in that mode. Use exact guards with contract_effect="additive", source="user", mode="redirect", and explicit fallback_mode="after_turn" for implementation refinement. Shared contract changes require an approved successor.
ouroboros_job_result(job_id) andsummarize the final job result and next step:
and any worktree_path / worktree_branch returned in job metadata. Do not present ooo evaluate as an automatic next step for Ralph results: the Ralph job contract preserves the evolution lineage_id, but it does not reliably preserve a separate execution session_id for the evaluate workflow. If a valid execution session_id is explicitly available from a separate run result, keep it distinct from the Ralph lineage_id and follow the ooo evaluate <session_id> contract; otherwise state that formal evaluation needs a real execution session and should not be invoked from the Ralph lineage id alone.
ooo unstuck, ooo interview, or a narrower Ralph retry
terminal surface. Summarize the Task completion/error state and lineage id; do not claim a local Ralph job can be polled or cancelled.
For attention_required, use at most one short-lived read-only verifier. Without that primitive, surface the evidence and do not ACT. Otherwise VERIFY → DECIDE from recommended_host_actions → LOG selected with ouroboros_record_conductor_decision → ACT only a menu-listed registered tool → LOG one completed, failed, or declined outcome. Ralph may use a directive only for the first and sole bounded successor generation (max_generations=1), and only when deterministic and non-relaxing.
These are English canonical instructions. Render them naturally in the user's conversation language.
| Skill action | MCP tool | | --- | --- | | Start Ralph loop | ouroboros_ralph | | Wait for progress | ouroboros_job_wait | | Fetch final result | ouroboros_job_result | | Cancel loop | ouroboros_cancel_job | | Inspect current status | ouroboros_job_status |
This is the key phrase. Ralph does not give up:
limits stop it.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 28,432 | 21,284 | -25% | 1 | 1 | 0% | 4,595 | 5,880 | +28% | 0 | 0 | — |
case-02 | fail→fail | 5,300 | 15,496 | +192% | 1 | 1 | 0% | 266 | 4,769 | +1693% | 0 | 0 | — |
case-03 | fail→fail | 5,743 | 12,635 | +120% | 1 | 1 | 0% | 729 | 3,961 | +443% | 0 | 0 | — |
case-04 | fail→pass | 12,862 | 10,021 | -22% | 1 | 1 | 0% | 2,116 | 4,050 | +91% | 0 | 0 | — |
case-05 | pass→pass | 15,293 | 5,342 | -65% | 1 | 1 | 0% | 2,421 | 3,847 | +59% | 0 | 0 | — |
case-06 | fail→pass | 12,802 | 8,467 | -34% | 1 | 1 | 0% | 2,378 | 4,439 | +87% | 0 | 0 | — |
case-07 | pass→pass | 9,809 | 5,646 | -42% | 1 | 1 | 0% | 1,523 | 3,788 | +149% | 0 | 0 | — |
case-08 | fail→pass | 9,581 | 5,385 | -44% | 1 | 1 | 0% | 1,561 | 3,847 | +146% | 0 | 0 | — |
case-09 | fail→pass | 17,602 | 5,482 | -69% | 1 | 1 | 0% | 2,508 | 3,530 | +41% | 0 | 0 | — |
case-10 | pass→pass | 15,686 | 4,788 | -69% | 1 | 1 | 0% | 2,653 | 3,797 | +43% | 0 | 0 | — |
case-11 | pass→pass | 9,027 | 6,061 | -33% | 1 | 1 | 0% | 1,257 | 3,646 | +190% | 0 | 0 | — |
case-12 | fail→pass | 15,604 | 4,472 | -71% | 1 | 1 | 0% | 2,258 | 3,570 | +58% | 0 | 0 | — |
case-13 | fail→pass | 6,139 | 3,237 | -47% | 1 | 1 | 0% | 1,004 | 3,448 | +243% | 0 | 0 | — |
case-14 | fail→pass | 12,482 | 3,150 | -75% | 1 | 1 | 0% | 1,636 | 3,402 | +108% | 0 | 0 | — |
case-15 | fail→pass | 15,012 | 2,469 | -84% | 1 | 1 | 0% | 2,095 | 3,307 | +58% | 0 | 0 | — |
case-16 | fail→pass | 15,944 | 7,207 | -55% | 1 | 1 | 0% | 2,547 | 3,940 | +55% | 0 | 0 | — |
case-17 | fail→pass | 14,382 | 8,618 | -40% | 1 | 1 | 0% | 2,410 | 4,490 | +86% | 0 | 0 | — |
case-18 | fail→pass | 12,790 | 5,973 | -53% | 1 | 1 | 0% | 2,076 | 3,618 | +74% | 0 | 0 | — |
case-19 | fail→pass | 18,584 | 6,333 | -66% | 1 | 1 | 0% | 2,884 | 3,997 | +39% | 0 | 0 | — |
case-20 | fail→pass | 12,396 | 6,263 | -49% | 1 | 1 | 0% | 2,092 | 3,774 | +80% | 0 | 0 | — |
case-21 | pass→pass | 11,242 | 10,226 | -9% | 1 | 1 | 0% | 1,751 | 4,069 | +132% | 0 | 0 | — |
case-22 | fail→pass | 16,332 | 3,134 | -81% | 1 | 1 | 0% | 2,225 | 3,161 | +42% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 20 counted toward the lift figure. The other 2 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +64 percentage points is the difference between those two pass rates over the 20 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.