Skip to main content
POST
Design an agent from a description
Describe the agent you want in plain language and get back the agent InstaView would build for you — the whole conversation, ready to create.
This does not create an agent. Nothing appears in your agent list, nothing can be called, and nothing is billable until you separately post the result to POST /agents. The 202 returned here created a composer session, not an agent.
That is the point of this endpoint: you can put “here is the agent I’d build for you” in front of a person, let them read it, change their mind twice, and only then create anything.

It answers before the agent exists

Designing an agent is a language-model call that takes tens of seconds, so this route does not hold your request open for it. It returns 202 straight away with a session id, and the design happens in the background.
Then poll GET /agents/composer/{sessionId} until it stops saying processing. It answers 202 while the work is running and 200 when it has finished, so you can branch on the status code without parsing the body:
Every five seconds is a sensible interval. Most designs land in well under a minute.
Or be told instead of asking. Send webhookId with the brief and we will call your webhook when a turn finishes — composer.completed carrying the same agent the poll would have given you, composer.failed carrying the reason and no agent.We only send the events that webhook subscribes to. Subscribing to one of the two is enough to be accepted, and is a reasonable choice, but you then hear nothing about the other outcome: subscribe to both, or poll for the one you did not take. Polling always works as well, and is always authoritative.
Two fields are required: your message, and the type of agent to design.
type is required and cannot change later. The channel decides which conversation steps are legal at all — a transfer to a person exists only on PHONE — so it has to be known before the agent is designed rather than guessed from your brief.
Everything else is optional and, if you send it, wins over what the composer chose — on this turn and on every later one. That is what name, language, duration, voiceId, backgroundSound, companyPhoneNumberId and metadata are for: pin the things you already know, and let the composer decide the rest.
Ask for a calling window in words. “Only call weekday mornings, and try twice” is understood, and the window comes back on the preview as callConfig — already in the shape POST /agents accepts, so it survives whether you post the preview back or just the composerSessionId. It is not a field of this route: to set one exactly rather than describe it, send callConfig in your create call, where it wins over whatever the composer chose. When neither of you says anything, a new agent calls Mon–Fri 09:00–18:00 in each contact’s own timezone.
You do not send a flow. flow, focus, guardrails, contextConfig and analyticsConfig are what the composer writes for you, and sending any of them is rejected with a 400 naming which. If you already have a flow, you do not need the composer — post it straight to POST /agents.

What the finished session contains

Once status is ready, the poll response carries the agent and the conversation:
The newest assistant message is the accompanying description: a plain-language account of the agent, in at most ten sentences — what it opens with, what it asks about, what it decides, and how it ends. It is written for a person, not for a parser. Its changes is a short list of labels for what the composer did: on the first turn what it built, on later turns what changed.

When the design fails

A brief the composer cannot turn into a valid agent does not fail your request — your request was already answered. The session ends up failed instead, and the poll tells you why:
COMPOSER_INVALID_RESULT is worth rephrasing for. Any other code is worth retrying unchanged.

What to do with the preview

agent is a body POST /agents accepts verbatim — no ids, no schemaVersion, and a conditional’s fallthrough already named by defaultBranch. Nothing to strip, nothing to fix up.

Change something first

Send another message to the session — “also ask about relocation”, “make it Slovak”.

Create it

Post the agent object, or just { "composerSessionId": "…" }.
The simplest way to create it is to hand back the session id and let us build exactly what you were shown:
Send fields alongside it to change your mind at the last moment — { "composerSessionId": "…", "name": "Backend Screen v2" } creates the previewed agent under a different name.
Wait for ready before creating. A session whose design has not finished has no agent to create, and posting its id is a 409 telling you to poll. A session whose later refinement is still running is fine: it still holds the last agent you were shown, and that is what gets created.
The conversation follows the agent. However you create it, the messages that designed it are attached to the new agent, so opening it in InstaView shows how it was built — and someone can carry on editing it there by hand.

Sessions expire

A session lives 30 days. After that, a preview nobody accepted is deleted along with its conversation; expiresAt on every response tells you when. Creating the agent ends the clock — a session that became an agent is kept.

Rate limits

Every call here designs an agent with a language model, so these routes carry their own limit on top of your key’s usual allowance: 6 per minute and 60 per hour for this endpoint, 10 per minute and 120 per hour for refining. Exceeding it is a 429.

Errors

These are the ways the request can fail. A design that fails after it has been accepted is not an error here — it is a failed session, described above.

Authorizations

Authorization
string
header
required

API key for authentication using Bearer scheme

Query Parameters

companyId
string

Required for ATS API keys to specify which company to access. Ignored for standard company API keys.

Body

application/json
message
string
required

What the agent should do, in plain language. The composer designs the whole conversation from this.

Maximum string length: 8000
Example:

"Screen senior backend devs. Ask about Go and Postgres, check notice period and salary expectation, then hand off to a recruiter if they're a strong fit."

type
enum<string>
required

The channel the agent will run on. Required, and fixed for the life of the session: it decides which conversation steps are available at all — a transfer to a person exists only on PHONE.

Available options:
ONLINE,
PHONE
Example:

"PHONE"

name
string

Name for the agent. Optional — the composer proposes one from your brief. Anything you send here wins, and keeps winning on later turns.

Required string length: 3 - 100
Example:

"Senior Developer Phone Screen"

language
enum<string>

Language of the conversation. When omitted, the composer follows the language of your brief.

Available options:
EN,
SK,
CS
duration
number

Target call length in minutes.

Required range: 1 <= x <= 180
voiceId
string

Voice for the agent.

backgroundSound
enum<string>

Ambient background sound.

Available options:
OFFICE,
OFF
companyPhoneNumberId
string

The number this agent should call from. PHONE agents only.

metadata
object

Custom metadata carried through to the agent you create from this session.

webhookId
string<uuid>

A webhook to notify when a turn on this session finishes, instead of polling. It must subscribe to composer.completed or composer.failed; only the events it subscribes to are sent, so subscribe to both to hear about every outcome. Pinned once here and used by every later refinement of this session.

Response

The turn was accepted and is running. Poll GET /agents/composer/{sessionId} for the result.

sessionId
string<uuid>
required

The session to poll, to send follow-up messages to, and to create the agent from.

status
enum<string>
required

Always processing here: the turn has been accepted and is running.

Available options:
processing
expiresAt
string<date-time>
required

When this session is deleted if you never create the agent. Sessions live 30 days.