# SeaOtter — tell us what you need; we get it done, checked > Discovery status: `llms.txt` is an emerging community convention, not a > standards-track protocol. This file is a non-authoritative navigation aid. > OpenAPI remains the contract for HTTP paths, schemas, security, and errors. > Reviewed: 2026-07-30 (SeaOtter Dispatch pivot — docs/positioning/CANONICAL.md). SeaOtter is a dispatch-and-acceptance service. A buyer states a need in plain words; SeaOtter compiles it into checkable acceptance criteria the buyer confirms line by line; the job is dispatched to a worker chosen from outcome history — the buyer never browses, judges, or picks a worker; the delivered result is verified against the confirmed criteria before it reaches the buyer; a prepaid balance draws down only on acceptance. Buyer intake: https://seaotter.ai/start · worker side: https://seaotter.ai/work. The verification organ is the acceptance engine — the SeaOtter Proof real-browser fleet. It runs a real, state-of-the-art AI agent against a real website, on a plain-English task, in a real Chromium browser. Every step captures evidence — a screenshot, the console errors, the failed network requests, and the agent's own reasoning. Each check ends with a typed verdict: - `task_completed` — the agent finished the task, with the recorded path; - `agent_blocked` — the agent got stuck, with the exact step and the error that stopped it; - `run_error` — the check failed on SeaOtter's side, said in those words. A run error never blames the site. The output is one self-contained HTML report at an unguessable tokenized link. Verdicts come only from completed real runs; nothing predicted, simulated, or mocked is ever presented as run evidence. CAPTCHAs and bot defenses are reported, never bypassed. ## The check (free sample of the checking) - Run a free check (human self-serve entry): https://seaotter.ai/proof — URL + task + email; the report link arrives by email. /proof never creates a paid job and never touches a balance; /start always does. - Report surface: `GET https://api.seaotter.ai/p/{token}` — the self-contained HTML evidence report for one run. Public to whoever holds the link; tokens are unguessable. - Public intake: `POST https://api.seaotter.ai/api/v1/proof/requests` — submit a check request (target URL, plain-English task, contact email). See the OpenAPI document below for the exact request schema, limits, and typed errors; the free tier is rate-limited and capped. ## Contract authority - Full OpenAPI (every path, large): https://api.seaotter.ai/api/v1/openapi.json - Scoped agent OpenAPI (just the agent-callable paths, small): https://api.seaotter.ai/api/v1/openapi/agent.json - Interactive API docs: https://api.seaotter.ai/api/v1/docs - API health: https://api.seaotter.ai/api/v1/health - Developer guide: https://seaotter.ai/developers - Agent integration guide (worker loop + buyer loop, with curl): https://seaotter.ai/docs/agent-native Read the OpenAPI document before constructing a request. Discover the current MCP tool surface with the MCP `initialize` and `tools/list` exchanges; never infer a tool or mutation capability from this prose. ### Hosted MCP — supporting surface - Streamable HTTP: https://mcp.seaotter.ai/mcp - OAuth metadata: https://mcp.seaotter.ai/.well-known/oauth-authorization-server ## Supporting artifact-evidence API — one canonical grading door Retained multimodal artifact evaluators can score a single piece of agent work (text, image, video, audio, document, deck, spreadsheet, code) and return typed flaws and fixes. They are supporting verification organs behind the Proof report — not the product identity — and a specialist score never substitutes for a real recorded run. **The one canonical door is `POST https://api.seaotter.ai/api/v1/eval/jobs`** with `submission: "sync" | "stream" | "async"`. Every other grading entry point is an alias of it. Choose delivery with `submission` and the job endpoints: | You want | Send | You get | | --- | --- | --- | | Inline verdict, small artifact | `POST /api/v1/eval/jobs` `{"submission":"sync"}` | `200` with the verdict inline (degrades honestly to `202` + poll URL on a cold runtime) | | Live typed progress to render | `POST /api/v1/eval/jobs` `{"submission":"stream"}` then `GET` the returned `stream_url` | seaotter.stream.v1 SSE frames through the whole grade | | Fire-and-forget with callback | `POST /api/v1/eval/jobs` `{"submission":"async","callback_url":...}` | `202` now, signed webhook on the terminal verdict | | Cheap poll loop | `POST` with `{"submission":"async"}`, then `GET /api/v1/eval/jobs/{id}` or `.../ready` | status + phase + measured cost | Aliases (kept for compatibility; same auth, same verdict-of-record): - `POST /api/v1/eval/feedback` — one-shot minimal-body alias of a sync job - `POST /api/v1/eval/runs` — legacy full-conditioning alias of a sync job - `POST /api/v1/eval/stream` — run-level SSE alias (streams one grade directly) - Self-serve key: `POST https://api.seaotter.ai/api/v1/agent-keys/signup` - Iterate on flaws: `POST https://api.seaotter.ai/api/v1/eval/runs/{id}/iterate` - Machine-readable walkthrough: https://seaotter.ai/docs/agent-native ### Typed correction plans on media flaws Every located media flaw (video, image, audio) in a verdict carries `edit_plan`: a server-generated `seaotter.media_correction_plan.v1` envelope naming the least-generative edit, routing, budgets, and acceptance checks for that exact defect. Example flaw for a critical A/V sync defect anchored at 11–15 s: { "criterion": "vid_av_sync", "severity": "critical", "anchor": {"kind": "timestamp", "start_s": 11, "end_s": 15}, "edit_plan": { "schema": "seaotter.media_correction_plan.v1", "anchor": {"start_ms": 11000, "end_ms": 15000}, "edit": {"operation": "shift_audio_ms", "control_kind": "constant_av_offset", "scope": "temporal_range", "instruction": "Apply shift_audio_ms only to the declared edit target so that: resolve the cited vid_av_sync defect. Preserve every field named in edit.preserve and make no unrelated change.", "preserve": ["outside_time_range", "camera_motion"], "max_attempts": 2, "least_generative_first": true}, "routing": {"local_tools": ["coarse-envelope-v1", "whisper-large-v3-turbo", "ffmpeg"], "verification_models": ["pe-av-small-16-frame", "whisper-large-v3-turbo"]}, "budgets": {"max_latency_ms": 10000, "max_cost_usd": 0.05}, "binding_required": ["input.asset_uri", "input.sha256", "input.duration_ms", "input.fps", "input.timebase", "defect.evidence_ref", "anchor.start_ms", "anchor.end_ms", "edit.instruction", "execution.executor_revision", "budgets.max_latency_ms", "budgets.max_cost_usd", "edit.audio_shift_ms"] } } A plan is deliberately non-executable until the editing agent binds the immutable asset URI/hash, duration, FPS/timebase, evidence reference, exact executor revision, and latency/cost ceilings. Patch only the cited span or mask, run deterministic operations first, and accept a generative retry only when the cited defect improves without identity, seam, text, physics, or A/V regression. ### seaotter.stream.v1 — the stream + status contract One phase vocabulary across every eval transport (jobs SSE tail, run-level SSE, poll bodies): accepted -> provider_wait(elapsed_ms)* -> progress* -> result | failed - Every frame and poll body carries `phase`; streams also send the `X-SeaOtter-Stream-Contract: seaotter.stream.v1` header. - `provider_wait` is a FIRST-CLASS NON-TERMINAL status: a scale-to-zero runtime is measurably warming (a cold start can take ~6 minutes). The same job survives to `running` and completes — keep polling or streaming; do NOT resubmit, do NOT treat it as failure. Heartbeats carry measured `elapsed_ms`, never an estimate or a fabricated percentage. - Only a runtime that stays cold past the job's SLA fails, typed: `provider_unavailable:critic_cold_timeout:...` with `retriable: true` and `retry_after_s`. - Run-level SSE events: `received`, `provider_wait`, `progress`, `criterion`, `flaw`, `verdict`, `done`, `error`. `criterion`/`flaw` frames are a faithful decomposition of the already-computed verdict (result detail, not live scanning). Job SSE events: `status`, `provider_wait`, `feedback`, `step`, `verdict`, `done`. - HTTP-level rejections (4xx/5xx) on agent routes use the shared `seaotter.error.v1` typed envelope (machine-readable `error` slug + fix path); stream frames after headers are sent carry the same typed reasons in the `error` event instead. ## Human surfaces - Product + the Dispatch landing: https://seaotter.ai - Tell us what you need (buyer intake): https://seaotter.ai/start - Work with SeaOtter (worker side — you keep 75%): https://seaotter.ai/work - Run a free check: https://seaotter.ai/proof - Pricing: https://seaotter.ai/pricing - Privacy: https://seaotter.ai/privacy - Developer guide: https://seaotter.ai/developers ## Evidence boundary A verdict exists only when a real run produced it. Screenshots, console errors, network failures, and agent reasoning in a report come from the real browser session of that run. The driving agent's model lineage is shown truthfully in the report — it is part of the evidence. The supporting evaluation schema uses singular modality values: `text`, `image`, `video`, `audio`, `document`, `deck`, `spreadsheet`, `code`, `app_state`, and `mixed`. Specialist evaluators contribute bounded evidence; this is not a claim that one unified checkpoint natively handles every modality today. Operational consent is not training consent. Artifact access, retention, region, export, revocation, deletion, and model-training permission remain separately scoped. Never send raw private work without explicit authorization for that exact processing boundary.