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

# Orchestrations

> Combine multiple agents into coordinated multi-agent systems.

Orchestrations coordinate multiple agents across multi-domain tasks. A coordinator agent analyzes incoming messages and delegates subtasks to specialized entity agents based on their role descriptions, then synthesizes the entity responses into a single reply.

## Common Patterns

Create an orchestration, add entity agents with clear role descriptions, then use the streaming endpoint. The coordinator handles delegation. Keep entity role descriptions specific and non-overlapping so the coordinator can route cleanly.

## CRUD

### POST /api/orchestrations

Create an orchestration.

<RequestExample>
  ```json Request theme={null}
  { "name": "Team", "strategy": "supervisor" }
  ```
</RequestExample>

<CodeGroup>
  ```python Python theme={null}
  requests.post(f"{BASE_URL}/api/orchestrations", headers=headers, json={"name": "Team", "strategy": "supervisor"})
  ```

  ```typescript TypeScript theme={null}
  await fetch(`${BASE_URL}/api/orchestrations`, { method: "POST", headers, body: JSON.stringify({ name: "Team", strategy: "supervisor" }) });
  ```

  ```bash cURL theme={null}
  curl -X POST '{BASE_URL}/api/orchestrations' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}" -H "Content-Type: application/json" -d '{"name": "Team"}'
  ```
</CodeGroup>

### GET /api/orchestrations

List all orchestrations.

<CodeGroup>
  ```python Python theme={null}
  requests.get(f"{BASE_URL}/api/orchestrations", headers=headers)
  ```

  ```typescript TypeScript theme={null}
  await fetch(`${BASE_URL}/api/orchestrations`, { headers });
  ```

  ```bash cURL theme={null}
  curl '{BASE_URL}/api/orchestrations' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}"
  ```
</CodeGroup>

### GET /api/orchestrations/{id}

Get orchestration with its entities.

<ParamField path="id" type="string" required>
  Orchestration ID
</ParamField>

<CodeGroup>
  ```python Python theme={null}
  requests.get(f"{BASE_URL}/api/orchestrations/{orch_id}", headers=headers)
  ```

  ```typescript TypeScript theme={null}
  await fetch(`${BASE_URL}/api/orchestrations/${orchId}`, { headers });
  ```

  ```bash cURL theme={null}
  curl '{BASE_URL}/api/orchestrations/{id}' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}"
  ```
</CodeGroup>

### PUT /api/orchestrations/{id}

Update orchestration config.

<ParamField path="id" type="string" required>
  Orchestration ID
</ParamField>

<CodeGroup>
  ```python Python theme={null}
  requests.put(f"{BASE_URL}/api/orchestrations/{orch_id}", headers=headers, json={"name": "Updated"})
  ```

  ```typescript TypeScript theme={null}
  await fetch(`${BASE_URL}/api/orchestrations/${orchId}`, { method: "PUT", headers, body: JSON.stringify({ name: "Updated" }) });
  ```

  ```bash cURL theme={null}
  curl -X PUT '{BASE_URL}/api/orchestrations/{id}' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}" -H "Content-Type: application/json" -d '{"name": "Updated"}'
  ```
</CodeGroup>

### DELETE /api/orchestrations/{id}

Delete an orchestration.

<ParamField path="id" type="string" required>
  Orchestration ID
</ParamField>

<CodeGroup>
  ```python Python theme={null}
  requests.delete(f"{BASE_URL}/api/orchestrations/{orch_id}", headers=headers)
  ```

  ```typescript TypeScript theme={null}
  await fetch(`${BASE_URL}/api/orchestrations/${orchId}`, { method: "DELETE", headers });
  ```

  ```bash cURL theme={null}
  curl -X DELETE '{BASE_URL}/api/orchestrations/{id}' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}"
  ```
</CodeGroup>

## Entities

### POST /api/orchestrations/{id}/entities

Add an agent as an entity.

<ParamField path="id" type="string" required>
  Orchestration ID
</ParamField>

<ParamField body="entity_type" type="string" required>
  Use `"agent"`. The route accepts any string ≤50 chars, but the orchestrator's execution path only invokes entities where `entity_type === "agent"`; other values are stored but silently skipped at run time.
</ParamField>

<ParamField body="entity_ref_id" type="string" required>
  UUID of the agent to add.
</ParamField>

<ParamField body="role_description" type="string">
  Free-text role hint shown to the coordinator when delegating. Replaces the prior `role` field used in older docs examples.
</ParamField>

<ParamField body="config" type="object">
  Per-entity overrides; defaults to `{}`.
</ParamField>

<ParamField body="position" type="integer">
  Sort order in list responses; defaults to `0`.
</ParamField>

<Note>
  The route returns 400 if either `entity_type` or `entity_ref_id` is missing. List/PUT responses key off `entity_ref_id` and `role_description`, so any client trying to round-trip will see the same field names.
</Note>

<RequestExample>
  ```json Request theme={null}
  {
    "entity_type": "agent",
    "entity_ref_id": "agent-uuid",
    "role_description": "Handles billing"
  }
  ```
</RequestExample>

<CodeGroup>
  ```python Python theme={null}
  requests.post(f"{BASE_URL}/api/orchestrations/{orch_id}/entities", headers=headers, json={"entity_type": "agent", "entity_ref_id": agent_id, "role_description": "Handles billing"})
  ```

  ```typescript TypeScript theme={null}
  await fetch(`${BASE_URL}/api/orchestrations/${orchId}/entities`, { method: "POST", headers, body: JSON.stringify({ entity_type: "agent", entity_ref_id: agentId, role_description: "Handles billing" }) });
  ```

  ```bash cURL theme={null}
  curl -X POST '{BASE_URL}/api/orchestrations/{id}/entities' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}" -H "Content-Type: application/json" -d '{"entity_type": "agent", "entity_ref_id": "agent-uuid", "role_description": "Handles billing"}'
  ```
</CodeGroup>

### GET /api/orchestrations/{id}/entities

List entities in the orchestration.

<ParamField path="id" type="string" required>
  Orchestration ID
</ParamField>

<CodeGroup>
  ```python Python theme={null}
  requests.get(f"{BASE_URL}/api/orchestrations/{orch_id}/entities", headers=headers)
  ```

  ```typescript TypeScript theme={null}
  await fetch(`${BASE_URL}/api/orchestrations/${orchId}/entities`, { headers });
  ```

  ```bash cURL theme={null}
  curl '{BASE_URL}/api/orchestrations/{id}/entities' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}"
  ```
</CodeGroup>

### PUT /api/orchestrations/{id}/entities/{eid}

Update an entity. Only `role_description`, `config`, and `position` are writable; any other top-level keys are silently ignored. `entity_type` and `entity_ref_id` are not updatable; create a new entity instead.

<ParamField path="id" type="string" required>
  Orchestration ID
</ParamField>

<ParamField path="eid" type="string" required>
  Entity ID
</ParamField>

<ParamField body="role_description" type="string">
  Free-text role hint shown to the coordinator when delegating.
</ParamField>

<ParamField body="config" type="object">
  Per-entity overrides.
</ParamField>

<ParamField body="position" type="integer">
  Sort order in list responses.
</ParamField>

<RequestExample>
  ```json Request theme={null}
  { "role_description": "Updated role" }
  ```
</RequestExample>

<CodeGroup>
  ```python Python theme={null}
  requests.put(f"{BASE_URL}/api/orchestrations/{orch_id}/entities/{entity_id}", headers=headers, json={"role_description": "Updated role"})
  ```

  ```typescript TypeScript theme={null}
  await fetch(`${BASE_URL}/api/orchestrations/${orchId}/entities/${entityId}`, { method: "PUT", headers, body: JSON.stringify({ role_description: "Updated role" }) });
  ```

  ```bash cURL theme={null}
  curl -X PUT '{BASE_URL}/api/orchestrations/{id}/entities/{eid}' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}" -H "Content-Type: application/json" -d '{"role_description": "Updated role"}'
  ```
</CodeGroup>

### DELETE /api/orchestrations/{id}/entities/{eid}

Remove an entity.

<ParamField path="id" type="string" required>
  Orchestration ID
</ParamField>

<ParamField path="eid" type="string" required>
  Entity ID
</ParamField>

<CodeGroup>
  ```python Python theme={null}
  requests.delete(f"{BASE_URL}/api/orchestrations/{orch_id}/entities/{entity_id}", headers=headers)
  ```

  ```typescript TypeScript theme={null}
  await fetch(`${BASE_URL}/api/orchestrations/${orchId}/entities/${entityId}`, { method: "DELETE", headers });
  ```

  ```bash cURL theme={null}
  curl -X DELETE '{BASE_URL}/api/orchestrations/{id}/entities/{eid}' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}"
  ```
</CodeGroup>

## Execution

### POST /api/orchestrations/{id}/run/stream

Run orchestration with streaming SSE. Includes delegation events.

<ParamField path="id" type="string" required>
  Orchestration ID
</ParamField>

<RequestExample>
  ```json Request theme={null}
  { "message": "Hello" }
  ```
</RequestExample>

<CodeGroup>
  ```python Python theme={null}
  requests.post(f"{BASE_URL}/api/orchestrations/{orch_id}/run/stream", headers=headers, json={"message": "Hello"}, stream=True)
  ```

  ```typescript TypeScript theme={null}
  await fetch(`${BASE_URL}/api/orchestrations/${orchId}/run/stream`, { method: "POST", headers, body: JSON.stringify({ message: "Hello" }) });
  ```

  ```bash cURL theme={null}
  curl -N -X POST '{BASE_URL}/api/orchestrations/{id}/run/stream' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}" -H "Content-Type: application/json" -d '{"message": "Hello"}'
  ```
</CodeGroup>

### GET /api/orchestrations/runs/{run_id}

Get orchestration run result.

<ParamField path="run_id" type="string" required>
  Run ID
</ParamField>

<CodeGroup>
  ```python Python theme={null}
  requests.get(f"{BASE_URL}/api/orchestrations/runs/{run_id}", headers=headers)
  ```

  ```typescript TypeScript theme={null}
  await fetch(`${BASE_URL}/api/orchestrations/runs/${runId}`, { headers });
  ```

  ```bash cURL theme={null}
  curl '{BASE_URL}/api/orchestrations/runs/{run_id}' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}"
  ```
</CodeGroup>

## Hooks

These endpoints register hooks against an orchestration using the same `ai.hooks` model as [agent hooks](/api-reference/agents#hooks): `event`, `type`, `config`, `matcher`, `enabled`, and `position`.

<Warning>
  **Orchestration hooks are not executed yet.** The CRUD endpoints below work (you can create, list, and delete hook rows), but the orchestration engine does not currently fire them at runtime, so a registered hook has no effect on an orchestration run today. Register them only for forward-compatibility. When execution lands, orchestration hooks will follow the [agent hook contract](/concepts/agents-tools#hooks--middleware) (events such as `OnRunStart`/`OnRunComplete`, types `http`/`rule`/`approval`). The `event` and `type` you send are stored verbatim and not validated.

  Hooks attached to a **member agent** also do not fire while that agent runs *inside* an orchestration; only [standalone agent runs](/api-reference/agents#hooks) execute hooks today. If you rely on an agent's approval or policy hook, run that agent directly rather than as part of an orchestration until this lands.
</Warning>

### POST /api/orchestrations/{id}/hooks

Add a hook.

<ParamField path="id" type="string" required>Orchestration ID</ParamField>

<ParamField body="event" type="string" required>Lifecycle event name. Stored verbatim; not validated.</ParamField>
<ParamField body="type" type="string" required>Hook handler type: `http`, `rule`, or `approval` (see the agent hook contract).</ParamField>
<ParamField body="config" type="object" required>Handler-specific configuration (for `http`, includes `url`).</ParamField>
<ParamField body="matcher" type="string">Optional filter narrowing when the hook fires.</ParamField>
<ParamField body="enabled" type="boolean">Defaults to `true`.</ParamField>
<ParamField body="position" type="integer">Execution order within the event. Defaults to `0`.</ParamField>

<RequestExample>
  ```json Request theme={null}
  {
    "event": "OnRunComplete",
    "type": "http",
    "config": { "url": "https://example.com/orch-hook" },
    "enabled": true,
    "position": 0
  }
  ```
</RequestExample>

<CodeGroup>
  ```python Python theme={null}
  requests.post(f"{BASE_URL}/api/orchestrations/{orch_id}/hooks", headers=headers, json={"event": "OnRunComplete", "type": "http", "config": {"url": "https://example.com/hook"}})
  ```

  ```typescript TypeScript theme={null}
  await fetch(`${BASE_URL}/api/orchestrations/${orchId}/hooks`, { method: "POST", headers, body: JSON.stringify({ event: "OnRunComplete", type: "http", config: { url: "https://example.com/hook" } }) });
  ```

  ```bash cURL theme={null}
  curl -X POST '{BASE_URL}/api/orchestrations/{id}/hooks' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}" -H "Content-Type: application/json" -d '{"event": "OnRunComplete", "type": "http", "config": {"url": "..."}}'
  ```
</CodeGroup>

### GET /api/orchestrations/{id}/hooks

List hooks for the orchestration, ordered by `position`.

<ParamField path="id" type="string" required>Orchestration ID</ParamField>

<CodeGroup>
  ```python Python theme={null}
  requests.get(f"{BASE_URL}/api/orchestrations/{orch_id}/hooks", headers=headers)
  ```

  ```typescript TypeScript theme={null}
  await fetch(`${BASE_URL}/api/orchestrations/${orchId}/hooks`, { headers });
  ```

  ```bash cURL theme={null}
  curl '{BASE_URL}/api/orchestrations/{id}/hooks' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}"
  ```
</CodeGroup>

### DELETE /api/orchestrations/{id}/hooks/{hook_id}

Remove a hook.

<ParamField path="id" type="string" required>Orchestration ID</ParamField>
<ParamField path="hook_id" type="string" required>Hook ID</ParamField>

<CodeGroup>
  ```python Python theme={null}
  requests.delete(f"{BASE_URL}/api/orchestrations/{orch_id}/hooks/{hook_id}", headers=headers)
  ```

  ```typescript TypeScript theme={null}
  await fetch(`${BASE_URL}/api/orchestrations/${orchId}/hooks/${hookId}`, { method: "DELETE", headers });
  ```

  ```bash cURL theme={null}
  curl -X DELETE '{BASE_URL}/api/orchestrations/{id}/hooks/{hook_id}' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}"
  ```
</CodeGroup>

## Sessions

Session-level reads on orchestrations. The streaming `/run/stream` endpoint returns a `session_id` you can use here to fetch history.

### GET /api/orchestrations/{id}/sessions

List the most recent 100 sessions for an orchestration. Each entry includes `session_id`, `run_count`, `first_message`, `last_activity_at`, and `created_at`.

<ParamField path="id" type="string" required>Orchestration ID</ParamField>

<CodeGroup>
  ```python Python theme={null}
  requests.get(f"{BASE_URL}/api/orchestrations/{orch_id}/sessions", headers=headers)
  ```

  ```typescript TypeScript theme={null}
  await fetch(`${BASE_URL}/api/orchestrations/${orchId}/sessions`, { headers });
  ```

  ```bash cURL theme={null}
  curl '{BASE_URL}/api/orchestrations/{id}/sessions' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}"
  ```
</CodeGroup>

### GET /api/orchestrations/{id}/sessions/{session_id}/messages

Assembled messages for a session. Each assistant message carries per-run reasoning replay metadata (`reasoning_requested`, `reasoning_duration_ms`, `reasoning`, `events`) so a chat UI can re-render the original "Thought for X.Xs" pill on refresh. Tool calls are attached per-message via `tool_calls`. The legacy top-level `events` field is preserved for older clients.

<ParamField path="id" type="string" required>Orchestration ID</ParamField>
<ParamField path="session_id" type="string" required>Session ID</ParamField>

<CodeGroup>
  ```python Python theme={null}
  requests.get(f"{BASE_URL}/api/orchestrations/{orch_id}/sessions/{session_id}/messages", headers=headers)
  ```

  ```typescript TypeScript theme={null}
  await fetch(`${BASE_URL}/api/orchestrations/${orchId}/sessions/${sessionId}/messages`, { headers });
  ```

  ```bash cURL theme={null}
  curl '{BASE_URL}/api/orchestrations/{id}/sessions/{session_id}/messages' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}"
  ```
</CodeGroup>

## Error Responses

Orchestration routes return `{"error": "<message>"}` (no structured error code field).

| Status | Description                                                             |
| ------ | ----------------------------------------------------------------------- |
| 400    | The orchestration has no entity agents; add at least one before running |
| 400    | Hook POST is missing one of `event`, `type`, or `config`                |
| 404    | No orchestration exists with the given ID                               |
| 404    | No hook exists with the given ID for this orchestration                 |
| 404    | No orchestration session with the given ID                              |
