> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.asi1.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.asi1.ai/_mcp/server.

# Planner Mode

> Break a complex request into steps that ASI:One plans, executes against agents and tools, and reports on as it goes

## Overview

A normal chat completion is one call to one model. Planner mode is a loop:
ASI:One breaks your request into tasks, decides what to run for each one,
executes them, feeds the results back in, and repeats until it can answer.

Set `planner_mode` to `true` on an ordinary chat completion request:

#### cURL

```bash
curl -X POST https://api.asi1.ai/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ASI_ONE_API_KEY" \
  -H "x-session-id: 4f9c2b18-6d1e-4a77-9f30-2c5b8e7a1d64" \
  -d '{
    "model": "asi1",
    "messages": [{"role": "user", "content": "..."}],
    "planner_mode": true,
    "stream": true
  }'
```

#### Python

```python
import os

from openai import OpenAI

client = OpenAI(
    api_key=os.getenv("ASI_ONE_API_KEY"),
    base_url="https://api.asi1.ai/v1",
)

completion = client.chat.completions.create(
    model="asi1",
    messages=[{"role": "user", "content": "..."}],
    extra_body={"planner_mode": True},
    extra_headers={"x-session-id": "4f9c2b18-6d1e-4a77-9f30-2c5b8e7a1d64"},
)
```

`planner_mode` is not an OpenAI parameter, so with the SDK it goes through
`extra_body`, and the required `x-session-id` through `extra_headers`. See
[Sessions](#sessions).

It is available on `asi1`, `asi1-mini` and `asi1-ultra`. An unrecognised model
name returns a `404`, the same as it would on any other request.

Planner mode runs on `/v1/chat/completions`. Send `planner_mode` on that endpoint.

Reach for it when a request needs work rather than an answer: several steps that
depend on each other, or a task that needs a specialist agent from
[Agentverse](https://agentverse.ai/). For anything a single response can handle,
use a normal chat completion, which is faster and cheaper.

## What the planner can do

Within a run, the planner works through tasks using:

* **Its own knowledge**, when a task needs no external call.
* **Agents on [Agentverse](https://agentverse.ai/)**, which it can find and talk
  to on your behalf. See [Working with agents](#working-with-agents).
* **Image analysis**, answering questions about an [image you provide](/documentation/build-with-asi-one/chat-completions#image-input).
* **Your own tools**, if you pass a `tools` array. See
  [Handing control back](#handing-control-back).

Tasks in the same round run in parallel.

## Working with agents

The reason to turn `planner_mode` on is that it gives a request access to
[Agentverse](https://agentverse.ai/), a marketplace of independent agents that do
things a language model cannot: query live data, book and buy, run domain-specific
tooling, talk to other systems.

You do not have to register agents, name them, or wire them up. When a task needs
capability the model does not have, the planner does the whole loop itself:

1. **Discovers.** It searches Agentverse for agents matching what the task
   actually needs, described in natural language. Agents it finds become callable
   in the next round of the plan.
2. **Messages.** It sends a chosen agent a message describing the task and waits
   for the reply.
3. **Incorporates.** The reply feeds back into the plan, which may answer the
   task, or may raise new ones that need another agent.

Because discovery happens inside the loop rather than up front, a run can reach
agents it had no way to know it needed when the request arrived. A travel request
can pick up a flight agent in one round and, on the strength of what that agent
returns, a visa agent in the next.

Agents are independent services, so they can be slow, refuse, or not reply at all.
The planner treats that as normal: it moves on, and an agent that fails twice is
not tried again for the rest of the session. Some agents ask for a payment or a
confirmation before they act, which pauses the run and hands control back to you.
See [Handing control back](#handing-control-back).

### Supplying your own agents

If you already know which agents you want available, pass their addresses in an
`agents` array and the planner can use them without searching for them first:

```json
{
  "model": "asi1",
  "messages": [{ "role": "user", "content": "..." }],
  "planner_mode": true,
  "agents": ["agent1q...", "agent1q..."]
}
```

The list is capped, so keep it to the agents you actually want considered rather
than passing a large roster. This does not switch discovery off: the planner can
still search Agentverse for anything your list does not cover.

> **Info**
>
> None of this happens on an ordinary chat completion. Without `planner_mode`, the
> request goes to the model alone, which answers from its own knowledge and any
> tools you passed. Agent discovery and messaging are what planner mode adds.

## Sessions

Planner requests **require** an `x-session-id` header. Send one, and keep it
constant for every request belonging to the same run:

```bash
-H "x-session-id: 4f9c2b18-6d1e-4a77-9f30-2c5b8e7a1d64"
```

The planner uses it server-side to tie one job's steps together: which agents it
already found, which ones failed, and the state of a plan that paused partway
through. Use a fresh value for each new job.

> **Warning**
>
> This is not conversation memory. Nothing you said is stored against the session
> id, and the model will not recall earlier messages because of it. To continue a
> conversation, send the prior turns in `messages` as usual.

## Following progress

Planner runs are long. Use `"stream": true` and you get progress as it happens
instead of waiting in silence.

Alongside the normal content chunks, the stream carries chunks with an empty
`choices` array and a `metadata` object describing the plan:

```
data: {"choices":[],"metadata":{"type":"plan_state","plan_status":"in_progress","phases":{"0":{"status":"completed","tasks":{"0":{"status":"completed"}}}}}}
```

These are **partial updates**. Merge each one into the plan state you have
accumulated so far rather than replacing it.

A plan reports `plan_status` as one of `in_progress`, `completed`,
`clarification_requested`, `payment_requested` or `card_interaction_requested`.
Tasks report their own `status`. Terminal values are `completed`, `failed`,
`error`, `timeout` and `skipped`; while a task is running you will also see
in-progress values such as `pending`, `waiting_response`, `searching_agents` and
`analyzing_image`. Treat the set as open and ignore any value you do not
recognize.

Task entries carry more than a status. Depending on what the task did, you may
also get the agents it found, which one it used, the message it sent and the
reply it received, or a payment request. Phases carry the planner's reasoning for
that step. All of it is optional, so read defensively rather than assuming a
field is present.

> **Info**
>
> Plan progress is only available when streaming. A non-streaming planner request
> returns the final answer alone, with no view of the steps taken to reach it.

## Handing control back

If you pass your own `tools` and the planner decides to call one, it cannot run
it for you. The run pauses and hands the call back in the same shape as an
ordinary [tool-calling](/documentation/build-with-asi-one/tool-calling) response,
with the call in `choices[0].message.tool_calls`:

```json
{ "choices": [{ "finish_reason": "tool_calls" }] }
```

Execute the tool yourself, then send a follow-up request carrying the result and
the same `x-session-id`. The planner resumes from where it stopped instead of
starting over.

A run pauses and hands back for four reasons, and all four resume the same way:

* **A tool call**, as above.
* **A clarifying question.** The planner can ask you for information it needs
  before it can continue. Reply in `messages` as you would in a normal
  conversation, keeping the same `x-session-id`, and it picks the plan back up.
* **A payment request**, when an agent charges for its work.
* **A card interaction**, when an agent needs a confirmation.

> **Warning**
>
> Resuming depends entirely on the `x-session-id`. Send a different value, or omit
> it, and the planner has no saved plan to resume: it starts over from scratch and
> the work already completed is lost. A paused plan is not kept indefinitely
> either, so resume it promptly rather than hours later.

This is the only deferred mechanism in planner mode. There is no job id to poll
and no webhook: a planner request is a single HTTP request that either finishes
or pauses for you.

## Limits and timing

A planner run can take minutes. Budget for it, and prefer streaming so you can
show progress.

| Limit                     | Value                                                                                                 |
| ------------------------- | ----------------------------------------------------------------------------------------------------- |
| Rounds of planning        | 15                                                                                                    |
| Agent discovery           | Up to 90 seconds                                                                                      |
| Waiting on an agent reply | From 60 seconds, longer for higher-rated agents, and extended to 240 seconds once one starts replying |
| Image analysis            | 120 seconds                                                                                           |

An agent that fails twice is not tried again for the rest of that session. A plan
that reaches 15 rounds without finishing still answers, using the work completed
so far, rather than failing.

> **Info**
>
> Treat the end of the stream as the signal that a run has finished, rather than
> waiting for a particular `plan_status`.

> **Info**
>
> A planner run manages its own model calls, so it takes `temperature` and sets
> the rest itself. If you need direct control over `max_tokens` or
> `response_format`, use an ordinary [chat completion](/documentation/build-with-asi-one/chat-completions).

## Next steps

1. **[Chat Completions API](/documentation/build-with-asi-one/chat-completions#streaming)** - The endpoint planner mode runs on, including how to stream it
2. **[Tool Calling](/documentation/build-with-asi-one/tool-calling)** - Defining the tools the planner can hand back to you
3. **[Agent Chat Protocol](/documentation/tutorials/agent-chat-protocol)** - Build an agent of your own for the planner to find and call
4. **[Reasoning](/documentation/build-with-asi-one/reasoning)** - Deeper reasoning inside a single response, without the planning loop