---
title: "Stateless action prediction"
method: POST
path: "/v1/predict"
tags: ["predict"]
---

# Stateless action prediction

`POST /v1/predict`

Send a screenshot + instruction; receive structured actions to execute on the target machine. Managed inference has a published 5-credit base plus the documented provider-visible trajectory-image, HD current/trajectory image, v1-engine, and combined system_prompt + trimmed instructions (>500 characters) surcharges. BYOK runs the complete harness on the selected Anthropic/OpenAI account, debits zero Coasty platform credits, and still returns real provider token usage and non-secret attribution. This is a direct CUA primitive: under a test Coasty key, provider-direct BYOK requires an explicit per-request X-LLM-Api-Key plus X-LLM-Provider and can bill that provider account. A body provider without the key header returns 422 LLM_KEY_NOT_CONFIGURED: Stored provider keys are unavailable for test API keys. Send X-LLM-Api-Key explicitly for direct BYOK. Test auth never resolves a stored live provider key. Task instruction is excluded from the managed prompt surcharge. Read effective deployed pricing from GET /v1/models under pricing.

## Headers

- `Idempotency-Key` string
- `X-LLM-Provider` 'anthropic' | 'openai'
- `X-LLM-Api-Key` string
- `X-LLM-Model` string

## Request body

- PredictRequest — Stateless screenshot-to-actions request. The current screenshot, every trajectory screenshot, and all remaining JSON together must fit the 15 MiB (15,728,640-byte) request-body cap; compress/downscale history or use a stateful session for long trajectories.
  - `screenshot` union, required — One static PNG/JPEG screenshot as raw base64 or an exact data:image/png;base64 / data:image/jpeg;base64 URI. Animated and multi-frame images are rejected. This per-image limit does not multiply the ordinary 15 MiB aggregate JSON request-body cap.
    - string
    - string
    - string
  - `instruction` string, required — Natural-language task instruction. This task text is not counted toward the custom-prompt surcharge.
  - `cua_version` 'v1' | 'v3' | 'v4' | 'v5' — v1 = baseline full pipeline. v3 = lean, v4 = autonomous, v5 = latest/default. For managed stateless predict, v3/v4/v5 share the low-latency single-call planner; sessions, runs, workflows, and BYOK predictions use the selected full engine. Inspect GET /models managed_stateless_predict_mode.
  - `model` 'default', nullable — Managed model alias. For BYOK model selection use llm.model.
  - `system_prompt` string, nullable — Optional custom prompt. Its full length plus trimmed instructions determines the custom-prompt surcharge; exactly the discovered threshold is free.
  - `instructions` string, nullable — Optional appended guidance. Its trimmed length plus system_prompt determines the custom-prompt surcharge; task instruction is excluded.
  - `screen_width` integer, nullable — Omit to use the screenshot's true size (measured server-side); no longer defaults to 1920.
  - `screen_height` integer, nullable — Omit to use the screenshot's true size (measured server-side); no longer defaults to 1080.
  - `trajectory` TrajectoryStep[] — Up to 19 prior screenshots; the current screenshot is the 20th provider image. Prior action coordinates use each step's declared dimensions or decoded image dimensions and are normalized server-side. All frames and JSON share the 15 MiB aggregate request cap, so compress or downscale history.
    - `screenshot` union, required — One static PNG/JPEG screenshot as raw base64 or an exact data:image/png;base64 / data:image/jpeg;base64 URI. Animated and multi-frame images are rejected. This per-image limit does not multiply the ordinary 15 MiB aggregate JSON request-body cap.
      - string
      - string
      - string
    - `screen_width` integer, nullable — Coordinate-space width for this step's actions. Supply with screen_height; omit both to use the decoded image width.
    - `screen_height` integer, nullable — Coordinate-space height for this step's actions. Supply with screen_width; omit both to use the decoded image height.
    - `actions` ActionResponse[] — unresolved $ref
    - `reasoning` string
  - `max_actions` integer
  - `tools` string[], nullable
  - `action_policy` ActionPolicy — Opt-in, fail-closed post-model action enforcement. The complete normalized batch is checked atomically before actions are returned or dispatched. allowed_actions and blocked_actions cannot overlap. Prediction, Session, and Parse surfaces use prediction action names such as type_text; direct Machine routes use command names such as type. Task, Workflow, and Schedule policies are create-time controls inherited across execution and recovery.
    - `allowed_actions` string[], nullable — Optional action allowlist. Values are trimmed and lowercased before validation; duplicates after normalization are rejected. Terminal done/fail/awaiting_human signals remain allowed.
    - `blocked_actions` string[] — Action denylist. Values are trimmed and lowercased before validation; duplicates after normalization are rejected.
    - `blocked_keys` string[] — Keys forbidden in key_press, key_combo, and modifier-bearing actions. Values are trimmed and lowercased; duplicates after normalization are rejected; esc aliases escape.
    - `block_window_close` boolean — Block explicit close commands and common Alt+F4, Ctrl/Cmd+W, and Cmd+Q shortcuts.
    - `max_actions` integer, nullable — Maximum number of actions admitted in one prediction/session step, parsed action batch, or direct Machine batch.
    - `coordinate_bounds` CoordinateBounds — Inclusive coordinate rectangle in the request screenshot's pixel space.
      - `min_x` integer
      - `min_y` integer
      - `max_x` integer, required
      - `max_y` integer, required
  - `include_reasoning` boolean
  - `include_raw_code` boolean
  - `llm` LlmConfig — Opt-in BYOK model selection. provider 'managed' (or omitting llm) keeps the platform default. There is deliberately no api_key field (422 if attempted): keys ride the X-LLM-Api-Key header or the encrypted /v1/llm/keys store only. Once BYOK is requested there is NO silent fallback to Coasty's platform LLM keys.
    - `provider` 'managed' | 'anthropic' | 'openai' — Whose LLM account runs the harness. Anything else is 422 LLM_PROVIDER_UNSUPPORTED.
    - `model` string, nullable — Main worker model. Defaults: claude-sonnet-5 (anthropic), gpt-5.6-sol (openai). Model ids are 1-256 characters, begin with a letter or number, and then use only letters, numbers, dot, underscore, colon, slash, plus, at-sign, or hyphen; invalid ids return 422 LLM_MODEL_INVALID. The selected provider can still reject an unknown or inaccessible model. It must be vision-capable.
    - `grounding_model` string, nullable — Override for pixel-coordinate grounding. Defaults to model. Grounding quality is tuned on the platform model; expect best results with the defaults.
    - `compaction_model` string, nullable — Override for trajectory compaction. Defaults to model. A cheaper model here is the classic cost tune.
    - `code_agent_model` string, nullable — Override for the code agent. Defaults to model.

## Response `200`

Predicted actions.

- PredictResponse
  - `request_id` string, required
  - `actions` ActionResponse[], required — unresolved $ref
  - `raw_code` string[]
  - `reasoning` string
  - `status` 'continue' | 'done' | 'fail', required — Authoritative model loop-control claim. done means the model believes the observed state or the proposed step outcome satisfies the instruction; it may coexist with mutating actions and is not proof of persistence. Execute only admitted actions, capture a fresh post-action screenshot, and verify application state before accepting business completion. fail ends the ordinary loop for this response.
  - `cua_version` string, nullable — Echo: the CUA engine version that actually served this call (e.g. "v5").
  - `screen_width` integer — Echo: the width the server actually used — the coordinate space the returned (x, y) are in.
  - `screen_height` integer — Echo: the height the server actually used — the coordinate space the returned (x, y) are in.
  - `usage` UsageInfo, required
    - `input_tokens` integer
    - `output_tokens` integer
    - `credits_charged` integer
    - `cost_cents` integer — USD-cent amount; the same numeric value as credits_charged (divide by 100 for USD).
    - `breakdown` object[], nullable — Self-auditable per-call cost breakdown; line credits sum to credits_charged. null on free/test/no-charge calls and /v1/parse.
      - `item` 'base' | 'trajectory' | 'hd_images' | 'engine' | 'custom_prompt', required
      - `credits` integer, required
      - `count` integer, nullable — Optional multiplier (e.g. number of HD screenshots billed); omitted where it adds nothing.
    - `billed` boolean — true on a real Coasty wallet debit; false on BYOK, test keys (sk-coasty-test-*), and idempotent replays (all return credits_charged: 0).
    - `llm_provider` 'managed' | 'anthropic' | 'openai' — Effective inference provider. Non-managed values identify provider-direct BYOK execution.
    - `llm_model` string, nullable — Effective BYOK model id; null for managed inference.
    - `llm_key_fingerprint` string, nullable — Non-secret SHA-256 prefix identifying the BYOK key; never the key itself.
    - `llm_key_source` 'header' | 'stored', nullable — Where the effective BYOK key came from; null for managed inference.
    - `platform_cost_exempt` boolean — true for BYOK. Coasty credits/cost are zero. Provider billing occurs only for provider-direct execution. Managed-mode test Task, Workflow, and schedule sandbox execution makes no provider call; test-auth BYOK intent on those async endpoints is rejected before execution.

## Other responses

- `400` — Invalid request body or parameters.
- `401` — Missing, invalid, or revoked API key. Pass `X-API-Key: sk-coasty-live-...` (or test).
- `402` — Insufficient balance for this operation. Direct metered API calls and managed-machine runtime use the prepaid Developer API wallet; scheduled execution is the documented consumer subscription-credit exception. Follow the operation's billing fields and top up the matching balance in the dashboard.
- `403` — API key lacks the required scope or tier-feature is unavailable on the caller's plan.
- `404` — Resource not found in this key's namespace.
- `409` — The resource state conflicts with this operation.
- `413` — The request body exceeds the endpoint limit.
- `422` — The JSON shape is valid but one or more values violate the endpoint contract.
- `429` — Rate or concurrency limit exceeded.
- `500` — Unexpected server error. Retry with exponential backoff.
- `502` — An upstream dependency returned an invalid response.
- `503` — A required service is temporarily unavailable.
- `504` — An upstream dependency timed out.

---

[API](https://skmtc.net/coasty/apis/coasty-public-api.md) · [All operations](https://skmtc.net/coasty/apis/coasty-public-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/coasty/coasty-public-api/revisions/f50d93b0d8a1/schema)
