# Your first real run

> Write instructions Cosmos can act on, pick a tier, attach your own metadata, and read the result.

## Write instructions like a ticket

Cosmos does best with the same things a teammate would need: the goal, the constraints, and how to know it's done.

```text
Create a small Express API in a folder named todo-api with GET/POST /todos
backed by SQLite. Add tests with node:test and run them.
Done means: all tests pass. Reply with the test output and how to start the server.
```

- **Say what "done" looks like.** "Run the tests and show me the output" beats "make sure it works".
- **Name files and folders** you care about.
- **Put limits in the instructions**: "don't add dependencies", "keep it under 100 lines".
- `input` can be up to **20,000 characters**, so paste the spec, error log or snippet it needs.

## Create the run

<CodeGroup>
```bash cURL
curl https://api.agent.clatterlabs.xyz/v1/runs \
  -H "Authorization: Bearer $CLATTER_API_KEY" \
  -H "X-Clatter-Account: $CLATTER_ACCOUNT_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "input": "Create a small Express API ... Reply with the test output.",
    "title": "todo-api",
    "tier": "max",
    "metadata": { "ticket": "OPS-112" }
  }'
```

```python Python
run = requests.post(
    "https://api.agent.clatterlabs.xyz/v1/runs",
    headers=headers,
    json={
        "input": "Create a small Express API ... Reply with the test output.",
        "title": "todo-api",
        "tier": "max",
        "metadata": {"ticket": "OPS-112"},
    },
).json()
```

```javascript JavaScript
const run = await fetch("https://api.agent.clatterlabs.xyz/v1/runs", {
  method: "POST",
  headers,
  body: JSON.stringify({
    input: "Create a small Express API ... Reply with the test output.",
    title: "todo-api",
    tier: "max",
    metadata: { ticket: "OPS-112" },
  }),
}).then((r) => r.json());
```
</CodeGroup>

| Field | Notes |
| --- | --- |
| `input` | Required. Up to 20,000 characters. |
| `title` | Optional, up to 80 characters. Defaults to the first line of `input`. |
| `tier` | `auto` (default), `flash`, `max` or `heavy`. See [Choose a tier](/agent/tiers). |
| `metadata` | Optional object up to 2 KB, returned as-is. Use it to link runs to your own records. |

## Wait for it

Pick whichever fits your code:

<Tabs>
<Tab title="Stream (recommended)">
Open the [event stream](/agent/streaming) and read events until `done`. You see each step as it happens.
</Tab>
<Tab title="Poll">
Call `GET /v1/runs/{id}` every few seconds until `status` is `completed`, `failed` or `cancelled`. Keep the interval at 2 seconds or more so you stay inside your key's rate limit.

```python
import time
while True:
    run = requests.get(f"{BASE}/v1/runs/{run_id}", headers=headers).json()
    if run["status"] in ("completed", "failed", "cancelled"):
        break
    time.sleep(3)
print(run["output"])
```
</Tab>
</Tabs>

## Read the result

A finished run looks like this:

```json
{
  "id": "4f0c2a6e-8d1b-4c3a-9f21-6b1e2d7c9a10",
  "object": "run",
  "status": "completed",
  "output": "All 6 tests pass. Start the server with: cd todo-api && npm start",
  "files": [{ "name": "test-output.txt", "bytes": 412 }],
  "steps": 23,
  "tier": "max",
  "usage": { "tokens": 96210 },
  "metadata": { "ticket": "OPS-112" }
}
```

Add `?include=files` to get each file's `content`. See [Files and outputs](/agent/files-and-outputs).
