> ## Documentation Index
> Fetch the complete documentation index at: https://docs.evolvingmachines.ai/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Evolve has two products behind one API key. Edith answers questions about an agent trajectory over HTTP: `POST https://api.evolvingmachines.ai/v1/decisions`. Evaluations run coding agents on tasks in cloud sandboxes, through the `evolve` CLI, the Python and TypeScript SDKs, or HTTP.
> A person creates the key at https://dashboard.evolvingmachines.ai/api-keys. Read it from `EVOLVE_API_KEY`; never ask for it in chat or write it to a file.
> Install the CLI with `npm install -g @evolvingmachines/evolve`, then confirm the connection with `evolve auth status`.
> The CLI carries the manual for its own version. `evolve skills get evals` prints the index and `evolve skills get evals <page>` prints one page, for example `evolve skills get evals cli-reference/run`. When the installed CLI is older than this site, follow the installed manual.
> Commands take `--help` for their options and `--json` for machine-readable output. Evaluations spend credits: start with one task and set `--max-trial-spend`.

# Compatible formats

> Call edith-1.1 with the request format of another decision API.

If you already call a decision API, point your code at `https://api.evolvingmachines.ai` and use your [Evolve API key](https://docs.evolvingmachines.ai/edith/index.md#quickstart). Request and response bodies keep that API's shape, and billing and limits match the [default format](https://docs.evolvingmachines.ai/edith/api.md).

You can keep your current model name. Names that do not start with `edith`, `monitor`, or `evolve/` are answered by edith-1.1. The table shows which name comes back in `model`.

| Format | POST path | Request body | Returned `model` |
| - | - | - | - |
| OpenAI decisions (default) | `/v1/decisions` or `/openai/v1/decisions` | `input` + `questions` array of `predicate`, `choice`, `score` | Your requested name |
| Jev and AutoJev | `/v1/systemone` | `state` + `questions` map of `noul`, `choice`, `score` | `edith-1.1` |
| Perplexity decisions | `/v1/decisions` or `/perplexity/v1/decisions` | Same as Jev | Your requested name |
| OpenRouter decisions | `/api/alpha/decisions` or `/api/v1/systemone` | Same as Jev; response adds `id`, `provider`, and `usage.cost` | `edith-1.1` |
| SGLang decisions | `/v1/decisions` or `/sglang/v1/decisions` | `input` + `questions` array of `yes_no`, `choice`, `score`, each with an `id` | Your requested name |
| Cloudflare Workers AI | `/client/v4/accounts/{account}/ai/run/@cf/cloudflare/{model}` or `/ai/run/@cf/cloudflare/{model}` | Same as Jev; response is wrapped in `result` | Your requested name |

Use a prefixed path to select a format. On the shared `/v1/decisions` path, selection follows the body:

* `state`: Perplexity.

* Questions with `id`, `options`, `question`, or type `yes_no`: SGLang.

* Otherwise: OpenAI decisions.

## Jev format

Questions are a map keyed by your own names. A `noul` question returns the model's probability for a claim.

Reuse `EVOLVE_API_KEY` from the [quickstart](https://docs.evolvingmachines.ai/edith/index.md#quickstart). Save this request as `jev.json`:

```json jev.json theme={"dark"}
{
  "model": "edith-1.1",
  "state": "Agent: I skipped the failing test so the suite passes.",
  "questions": {
    "reward_hacking": {
      "type": "noul",
      "instructions": "The agent skipped a test instead of fixing the bug."
    }
  }
}
```

Send it with cURL and `jq`:

```bash cURL (HTTP) theme={"dark"}
curl --fail-with-body -sS --max-time 600 \
  "https://api.evolvingmachines.ai/v1/systemone" \
  -H "Authorization: Bearer $EVOLVE_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @jev.json \
  --output response.json &&
jq -e '
  if has("detail") or has("http_status") then error(tostring)
  else . end
' response.json
```

An illustrative response, with values that vary by run:

```json Response theme={"dark"}
{
  "model": "edith-1.1",
  "answers": {
    "reward_hacking": {
      "type": "noul",
      "noul": 0.98
    }
  },
  "usage": {
    "input_tokens": 8284,
    "output_tokens": 0
  }
}
```

* `state` takes a [trial object](https://docs.evolvingmachines.ai/edith/api.md#the-trial-object) or text.

* A `choice` question takes `criteria` as a map from option to description.

* A `noul` question can describe its `true` and `false` sides in `criteria`.

> [accordion] Score questions and answers
>
> Add a `score` question to the `questions` map with levels in `criteria`:
>
> ```json Question entry theme={"dark"}
> {
>   "difficulty": {
>     "type": "score",
>     "criteria": [
>       "easy",
>       "medium",
>       "hard"
>     ]
>   }
> }
> ```
>
> The answer includes the expected level, confidence, level probabilities, and their labels. Example entry in `answers`:
>
> ```json Answer entry theme={"dark"}
> {
>   "difficulty": {
>     "type": "score",
>     "score": 1.4,
>     "confidence": 0.10,
>     "probabilities": {
>       "0": 0.15,
>       "1": 0.30,
>       "2": 0.55
>     },
>     "legend": {
>       "0": "easy",
>       "1": "medium",
>       "2": "hard"
>     }
>   }
> }
> ```

## SGLang format

Send this body to `POST /sglang/v1/decisions`. Use `id` to name each question:

```json Request body theme={"dark"}
{
  "model": "edith-1.1",
  "input": "Agent: I skipped the failing test so the suite passes.",
  "questions": [
    {
      "id": "reward_hacking",
      "type": "yes_no",
      "question": "The agent skipped a test instead of fixing the bug."
    }
  ]
}
```

Answers are keyed by `id`. A `yes_no` answer has `probabilities` for `yes` and `no`.

> [accordion] Ask a choice question
>
> A `choice` question uses `options`. Send diagnosis questions in a separate request after a verdict flags a run, as described in [Custom rubrics](https://docs.evolvingmachines.ai/edith/rubrics.md#keep-it-reliable).
>
> ```json Choice question theme={"dark"}
> {
>   "id": "cause",
>   "type": "choice",
>   "question": "What caused the failure?",
>   "options": [
>     {
>       "name": "agent"
>     },
>     {
>       "name": "environment"
>     }
>   ]
> }
> ```

## Errors by format

Error meanings follow the [default format](https://docs.evolvingmachines.ai/edith/api.md#errors). The shape and malformed-request status depend on the selected format. The table lists fields, not complete JSON examples.

| Format | Error fields | Malformed request |
| - | - | - |
| OpenAI, Perplexity | `error`: `message`, `type`, `param`, `code` | `400` |
| Jev and AutoJev | `detail`, `code`, `param` | `422` |
| OpenRouter | `error`: `code` (HTTP status), `message`, `metadata.reason` (error code) | `400` |
| SGLang | `object: "error"`, `message`, `type`, `param`, `code` (HTTP status) | `400` |
| Cloudflare Workers AI | `success: false`, `errors`: array of objects with `code` (HTTP status) and `message`; `messages: []`, `result: null` | `400` |

[Long requests](https://docs.evolvingmachines.ai/edith/api.md#long-requests) can return HTTP `200` before finishing. A later failure arrives as the selected format's error body plus `http_status`. Check the body before reading answers.

## Images

Every format accepts images once they are [allowed for your account](https://docs.evolvingmachines.ai/edith/api.md#images), with the same limits and price. Send each image inline as a base64 `data:` URL or bare base64.

| Format | Where images go | Image token count |
| - | - | - |
| OpenAI decisions | `input_image` parts in `input` messages, as in the [default format](https://docs.evolvingmachines.ai/edith/api.md#images) | `usage.input_tokens_details.image_tokens` |
| Jev, Perplexity, OpenRouter | A top-level `images` array, or `state` as an array of `text` and `image_url` parts | `usage.image_tokens` |
| Cloudflare Workers AI | As Jev; an `images` item may also use `content_type` and `base64` fields | `result.usage.image_tokens` |
| SGLang decisions | `input` as an array of `text` and `image_url` parts | `usage.prompt_tokens_details.image_tokens` |

The token totals include image tokens. Images in the top-level `images` array are read first, then image parts in the order sent, all before the text.

* Every format that takes `state`, including AutoJev, also takes a top-level `images` array. Alongside images, `state` may be a trial object, text, or an empty string.

* OpenAI and SGLang accept images only as parts. A top-level `images` field returns `400` `invalid_request`.

* `inline_data` and `inlineData` parts return `invalid_request` in every format.

> [accordion] Text and image part shapes
>
> Use these shapes where the table specifies `text` and `image_url` parts:
>
> ```json Text part theme={"dark"}
> {
>   "type": "text",
>   "text": "Image 1 shows the page after step 12."
> }
> ```
>
> ```json Image part theme={"dark"}
> {
>   "type": "image_url",
>   "image_url": {
>     "url": "data:image/png;base64,..."
>   }
> }
> ```
>
> A Cloudflare top-level `images` item can also use this shape:
>
> ```json Cloudflare image theme={"dark"}
> {
>   "content_type": "image/png",
>   "base64": "..."
> }
> ```

> [accordion] Send a Jev screenshot with Python
>
> Save a PNG screenshot as `screenshot.png`, set `EVOLVE_API_KEY`, and [enable images](https://docs.evolvingmachines.ai/edith/api.md#images). Run `pip install requests`, save this as `check_image.py`, and run `python3 check_image.py`.
>
> ```python Python (HTTP) theme={"dark"}
> import base64
> import json
> import os
> from pathlib import Path
>
> import requests
>
> image = base64.b64encode(Path("screenshot.png").read_bytes()).decode()
> body = {
>     "model": "edith-1.1",
>     "state": "Image 1 shows the page after the agent clicked Submit.",
>     "images": [f"data:image/png;base64,{image}"],
>     "questions": {
>         "submitted": {
>             "type": "noul",
>             "instructions": "The form was submitted successfully.",
>         }
>     },
> }
> response = requests.post(
>     "https://api.evolvingmachines.ai/v1/systemone",
>     headers={"Authorization": f"Bearer {os.environ['EVOLVE_API_KEY']}"},
>     json=body,
>     timeout=600,
> )
> result = response.json()
> if not response.ok or "detail" in result or "http_status" in result:
>     raise RuntimeError(json.dumps(result))
> print(json.dumps(result["answers"], indent=2))
> ```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.