> **Shapeless documentation index**
> Fetch https://shapelessai.com/llms.txt to discover every page before exploring further.
> Every page also answers Markdown: append `.md` to its path, or send `Accept: text/markdown`.

# Jobs

Durable runs: hand the agent team a goal, walk away, and collect the posts, carousels and video it made.

*Verified 2026-09-14. Source: https://shapelessai.com/docs/jobs*

A post you already wrote goes out through [Posts](/docs/posts). A job is the other direction: you
hand over a goal and the agent team researches, writes, designs and renders, then leaves the
result in the queue for approval.

A job is durable. You send a goal, get a `202` with its id, and the run keeps going whether or not
you stay connected - which is the only shape that survives a terminal closing, a lambda timing out
or a cron window ending.

## Start one

```bash
curl -s https://shapelessai.com/api/v1/jobs \
  -H "Authorization: Bearer $SHAPELESS_API_KEY" -H "Content-Type: application/json" \
  -d '{"goal":"Draft three posts about our beta launch","label":"Beta launch","budgetUsd":2.5}'
# 202 {"id":"j_123","title":"Beta launch","status":"running"}
```

```bash
shapeless jobs create draft three posts about our beta launch --label "Beta launch" --budget 2.50 --watch
```

```jsonc
// MCP
{ "tool": "jobs_create", "arguments": { "goal": "Draft three posts about our beta launch", "budgetUsd": 2.5 } }
```

Needs `write`. `label` becomes the title; without one the goal's first line is. `budgetUsd` caps
what the run may spend. `timezone` tells it what "tomorrow morning" means.

## Watch it, or come back

| Method | Path | Scope | Purpose |
| --- | --- | --- | --- |
| GET | `/api/v1/jobs` | `read` | The list, 200 per page, newest first, with a `nextCursor`. |
| GET | `/api/v1/jobs/[id]` | `read` | Transcript, `status`, `live`, and an outputs summary. |
| POST | `/api/v1/jobs/[id]/messages` | `write` | Another turn on the same job. |
| GET | `/api/studio/tail?conversationId=[id]` | `read` | The live event stream. |
| POST | `/api/studio/stop` | `write` | Stop it. |

Follow the run rather than polling it: `shapeless jobs tail <id>`, or the `jobs_tail` MCP tool,
which holds one bounded call (60 seconds or 200 events) and answers a cursor to resume from. A
job with no live stream answers `{live: false}` instead of erroring, and a finished one replays
and closes.

`jobs_brief` is the cheap read before replying: the last 30 messages clipped, reasoning and
tool-activity dropped, an artifact inventory, and post counts per queue status. Deterministic, no
model in the loop. `jobs_get` still gives the whole transcript.

## Resume a stuck run

Posting another message rebuilds the conversation server-side from the stored transcript, so
"continue" is a real resume, not a fresh start:

```bash
shapeless jobs continue j_123 keep going, but make the second post shorter --watch
```

## Attach files

`attachments` puts files on the message itself, and the agent **sees** them: an image's pixels are
inlined for that turn, video and PDF go over by storage URI, and the media key is named in the text
so it survives in history after the pixels are gone.

```jsonc
{
  "goal": "Does this thumbnail work for the launch post?",
  "attachments": [
    { "name": "thumb.png", "mediaKey": "chat-uploads/<account>/thumb-mt1z.png", "contentType": "image/png" },
    { "name": "notes.md", "text": "Launch is Thursday. Tone: plain, no hype." }
  ]
}
```

Up to **6** per message. Each entry needs a `name` and either `text` (inlined, 24k characters) or a
`mediaKey`. Get a key by uploading to `PUT /api/studio/attachments/[filename]` (10MB images, 30MB
video and PDF; filenames are `[A-Za-z0-9._-]`), or name any media key the account already owns - a
brand asset, something an earlier run made. A key belonging to another account is a `400` naming
the file, not a run that dies halfway. A malformed entry is a `400` too: attachments are never
dropped silently.

The CLI and MCP take local paths directly:

```bash
shapeless jobs create does this thumbnail work? --attach ./thumb.png --attach ./notes.md
```

## Cast an actor

An actor is workspace-level identity - a face, a voice, a style, a memory - that posts and jobs
cast. `characters` on a job is that cast, by slug or id:

```bash
shapeless characters list                # who exists, and how each voice was made
shapeless jobs create make the explainer short --characters maya,nova
```

The agent is shown the whole roster either way, so it reuses an actor that fits instead of
inventing another one. A ref that names nobody is a `400` naming it, never a run that silently
stars nobody.

## Handing work back to the human

Every job result carries `url` - `https://shapelessai.com/studio/c/<id>` - the conversation the
human opens to see what happened and approve what came out. Hand it over rather than pasting a
transcript.

## Money

A job spends credits: research, writing, images, video, voice. Free accounts carry $5 a month, refilled monthly.
`budgetUsd` caps one run. An empty wallet is a `402` with `code: "trial_exhausted"`, never a run
that quietly does less. `GET /api/me` carries the balance. Composing, scheduling and
publishing through the rail spend nothing - only the agent team does.
