Agent mode APIs in Genie Agents

Agent mode APIs let you run Agent mode programmatically instead of through the Azure Databricks UI. Use them to integrate Agent mode into your own applications, such as chatbots, scheduled reports, and internal tools.

Important

The Genie Agents Agent mode APIs are in Beta.

Note

Agent mode was formerly known as Research Agent. Genie Agents were formerly known as Genie Spaces.

How Agent mode APIs work

With the Agent mode APIs, you send a natural-language question to a Genie Agent. It creates and refines a research plan, runs SQL queries, iterates based on each result, and returns a report with citations and supporting tables. Results stream to your client as Server-Sent Events (SSE).

The APIs cover the endpoints, request and response formats, and streaming event types needed to communicate with Agent mode directly. For the concept overview and the UI experience, see Agent mode in Genie Agents.

Requirements

To use the Agent mode APIs, your workspace must meet the following requirements:

To enable the APIs for your workspace, contact your Azure Databricks account team with the workspace IDs where you want the feature. After the request is approved, a workspace admin turns on Genie Agents Agent Mode API from the Previews menu.

Get started

The following examples show how to send a prompt and read the streamed response.

Send your first prompt with curl

The following request sends a natural-language question to a Genie Agent and streams the response as an SSE:

curl -N --no-buffer \
  -X POST "https://${DATABRICKS_HOST}/api/2.0/genie/agents/${AGENT_ID}/responses" \
  -H "Authorization: Bearer ${DATABRICKS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "input": [
      {
        "type": "message",
        "role": "user",
        "content": [{"type": "input_text", "text": "What were our top 10 customers by revenue last quarter?"}]
      }
    ]
  }'

Events arrive as event: and data: pairs:

event: response.created
data: {"type":"response.created","sequence_number":0,"response":{"object":"response","id":"01f14fe4e34b...","model":"genie-agent","status":"in_progress","output":[],"conversation_id":"01f14fe4e338..."}}

event: response.output_item.added
data: {"type":"response.output_item.added","output_index":0,"sequence_number":1,"item":{"type":"reasoning","id":"01f14fe4f248...","status":"in_progress","content":[{"type":"reasoning_text","text":"I need to find revenue data..."}],"summary":[]}}

event: response.completed
data: {"type":"response.completed","sequence_number":42,"response":{"object":"response","id":"01f14fe4e34b...","model":"genie-agent","status":"completed","output":[...],"conversation_id":"01f14fe4e338...","created_at":1748383200}}

Read the stream with the Databricks OpenAI client (Python)

Install the client:

pip install databricks-openai

Create a response and handle each event as it arrives:

from databricks.sdk import WorkspaceClient
from databricks_openai import DatabricksOpenAI

AGENT_ID = "<your-agent-id>"  # Same as your Genie Agent ID

w = WorkspaceClient()
host = f"https://{w.config.host}" if not w.config.host.startswith("http") else w.config.host

client = DatabricksOpenAI(workspace_client=w)
client.base_url = f"{host}/api/2.0/genie/agents/{AGENT_ID}"

stream = client.responses.create(
    model="genie-agent",
    input=[
        {
            "type": "message",
            "role": "user",
            "content": [{"type": "input_text", "text": "What were our top 10 customers by revenue last quarter?"}],
        }
    ],
    stream=True,
)

conversation_id = None
for event in stream:
    if event.type == "response.created":
        conversation_id = event.response.conversation_id
    elif event.type == "response.output_item.done":
        print(f"Output item: {event.item.type}")
    elif event.type == "response.completed":
        print(f"Done: {event.response.status}")
    elif event.type == "response.failed":
        print(f"Failed: {event.response.error}")

Send a follow-up prompt

To continue a conversation, pass the conversation_id from the first response:

stream = client.responses.create(
    model="genie-agent",
    input=[
        {
            "type": "message",
            "role": "user",
            "content": [{"type": "input_text", "text": "Break that down by region"}],
        }
    ],
    stream=True,
    extra_body={"conversation_id": conversation_id},
)

The agent retains context from previous turns and can reference earlier queries and results.

API reference

The Agent mode APIs cover the available endpoints, the request and response formats, the SSE event lifecycle, the data models, and the error codes.

Base URL

All endpoints are relative to the following base URL:

https://<workspace-url>/api/2.0/genie/agents

Note

The agent_id in each path is the Genie Agent ID, the same 32-character hexadecimal identifier that appears in the Genie Agent URL.

Endpoints

The APIs provide the following endpoints:

Method Path Description
POST /{agent_id}/responses Create a response as an SSE stream.
GET /{agent_id}/conversations/{conversation_id}/items List all items in a conversation.

Create a response

Creates a new Agent mode response. Returns an SSE stream that delivers output items in real time as Agent mode runs.

POST /{agent_id}/responses

Path parameters

The endpoint accepts the following path parameter:

Parameter Type Required Description
agent_id string Yes The ID of the Genie Agent. A 32-character lowercase hexadecimal string.

Request body

The request body accepts the following fields:

Field Type Required Default Description
input array<InputItem> Yes None The input items. The array must contain exactly one message item with role: "user" that holds the question. Multi-turn context is managed server-side, so use conversation_id for follow-ups instead of passing prior messages in input.
conversation_id string No null The ID of an existing conversation to continue. When omitted, a new conversation is created.

SSE event lifecycle

The stream opens with a response.created event, streams output items, then closes with a terminal event:

response.created                    (once, stream opened)
  -> response.output_item.added     (0..N, new item appears)
  -> response.output_item.updated   (0..N, item content changed)
  -> response.output_item.done      (0..N, item finalized)
  -> response.completed             (once, terminal success)
     OR response.failed             (once, terminal failure)

Every event carries a monotonically increasing sequence_number that you can use for ordering.

SSE event types

The stream emits the following event types.

response.created

Emitted once at the start. Contains a Response object with status: "in_progress" and an empty output array.

event: response.created
data: {
  "type": "response.created",
  "sequence_number": 0,
  "response": {
    "object": "response",
    "id": "01f15a22a7a816299374da7bc4264025",
    "model": "genie-agent",
    "status": "in_progress",
    "output": [],
    "conversation_id": "01f15a22a79a1699ab5e7f59563c5655",
    "created_at": 1748383200
  }
}

response.output_item.added

Emitted when a new output item first appears. The item might still be in_progress.

event: response.output_item.added
data: {
  "type": "response.output_item.added",
  "output_index": 0,
  "sequence_number": 1,
  "item": {
    "type": "reasoning",
    "id": "01f14fe4f24818d79f3e5963c31ec151",
    "status": "in_progress",
    "content": [
      {"type": "reasoning_text", "text": "I need to find the revenue data..."}
    ],
    "summary": []
  }
}

response.output_item.updated

Emitted when an existing item's content changes, such as when query results arrive for a function_call_output. Uses the same payload shape as response.output_item.added.

response.output_item.done

Emitted when an output item reaches its final state. Uses the same payload shape as response.output_item.added. If an item arrives already completed, both the added and done events are emitted in sequence.

response.completed

Terminal success event. Wraps the final Response with all output items.

event: response.completed
data: {
  "type": "response.completed",
  "sequence_number": 42,
  "response": {
    "object": "response",
    "id": "01f14fe4e34b1b2293908bcece575499",
    "model": "genie-agent",
    "status": "completed",
    "output": [ ... ],
    "conversation_id": "01f14fe4e33816c6aa264b4661f998ea",
    "created_at": 1748383200
  }
}

response.failed

Terminal failure event. The Response has status: "failed" and an error object. A system error message item is emitted as response.output_item.added immediately before this event. For the full list of codes, see Streaming error codes.

event: response.failed
data: {
  "type": "response.failed",
  "sequence_number": 5,
  "response": {
    "object": "response",
    "id": "01f14fe4e34b1b2293908bcece575499",
    "model": "genie-agent",
    "status": "failed",
    "output": [ ... ],
    "error": {
      "type": "server_error",
      "code": "sql_execution_error",
      "message": "Table 'sales' does not exist"
    },
    "conversation_id": "01f14fe4e33816c6aa264b4661f998ea",
    "created_at": 1748383200
  }
}

Concurrency

Only one response can be generated per conversation at a time. A second request to a conversation that already has an in-progress response returns an HTTP 409:

HTTP 409
{"error": {"type": "RESOURCE_CONFLICT", "message": "A response is already being generated for conversation <id>"}}

Timeouts

The SSE stream has a server-side timeout of 90 minutes. Because Agent mode runs multi-step reasoning and SQL execution, keep your HTTP connection open for the full duration.

List conversation items

Retrieves the output items in a conversation as a flat list. Items from all turns are combined in chronological order, including user messages, reasoning, queries, results, and reports. This endpoint supports cursor-based pagination through the after and limit query parameters.

GET /{agent_id}/conversations/{conversation_id}/items

Use this endpoint to:

  • Display the full conversation history in your application.
  • Recover results after an SSE stream disconnects. Call this endpoint after the response completes.
  • Fetch large conversations incrementally instead of loading all items at once.

Path parameters

The endpoint accepts the following path parameters:

Parameter Type Required Description
agent_id string Yes The ID of the Genie Agent. A 32-character lowercase hexadecimal string.
conversation_id string Yes The ID of the conversation.

Query parameters

The endpoint accepts the following query parameters:

Parameter Type Required Default Description
limit integer No 100 The maximum number of items to return. Range: 1 to 100.
after string No None The pagination cursor. Pass last_id from a previous response to fetch the next page.
order string No asc The sort order. Use asc for chronological (oldest first) or desc for reverse chronological (newest first).

Example requests

Retrieve all items in a conversation:

GET /api/2.0/genie/agents/01f14fe4e338.../conversations/01f14fe4e338.../items

Limit the page size:

GET /api/2.0/genie/agents/01f14fe4e338.../conversations/01f14fe4e338.../items?limit=5

Return the newest items first:

GET /api/2.0/genie/agents/01f14fe4e338.../conversations/01f14fe4e338.../items?order=desc&limit=5

Fetch the next page:

GET /api/2.0/genie/agents/01f14fe4e338.../conversations/01f14fe4e338.../items?limit=5&after=01f14fe4f24e10beacaa1720d4b79b59_output

Response

The response has Content-Type: application/json and is a paginated list envelope with "object": "list":

{
  "data": [
    {
      "type": "message",
      "role": "user",
      "content": [{ "type": "input_text", "text": "What were our top 10 customers by revenue last quarter?" }],
      "id": "01f14fe4e34b1b2293908bcece575499_input",
      "status": "completed"
    },
    {
      "type": "reasoning",
      "id": "01f14fe4f24818d79f3e5963c31ec151",
      "status": "completed",
      "content": [{ "type": "reasoning_text", "text": "I'll query the revenue table grouped by customer..." }],
      "summary": []
    },
    {
      "type": "function_call",
      "id": "01f14fe4f24e10beacaa1720d4b79b59",
      "call_id": "01f14fe4f24e10beacaa1720d4b79b59",
      "status": "completed",
      "name": "execute_sql",
      "arguments": "{\"title\": \"Top 10 Customers\", \"sql\": \"SELECT customer, SUM(revenue) AS total FROM sales GROUP BY customer ORDER BY total DESC LIMIT 10\"}"
    },
    {
      "type": "function_call_output",
      "id": "01f14fe4f24e10beacaa1720d4b79b59_output",
      "call_id": "01f14fe4f24e10beacaa1720d4b79b59",
      "status": "completed",
      "output": "Top 10 Customers\n\n| customer | total |\n| --- | --- |\n| Acme Corp | 1500000 |\n| Globex | 1200000 |"
    },
    {
      "type": "message",
      "id": "01f14fe5383f184a97ca1178af0d9356",
      "role": "assistant",
      "status": "completed",
      "content": [
        {
          "type": "output_text",
          "text": "Here are your top 10 customers by revenue last quarter [1](https://host/genie/rooms/01f14fe4e338.../chats/01f14fe4e338...?o=12345&gra_focus=01f14fe4f24e...)."
        },
        {
          "type": "output_text",
          "text": "| customer | total |\n| --- | --- |\n| Acme Corp | 1500000 |\n| Globex | 1200000 |",
          "metadata": {
            "columns": [
              { "name": "customer", "type": "STRING" },
              { "name": "total", "type": "DOUBLE" }
            ],
            "preview_rows": [
              ["Acme Corp", "1500000"],
              ["Globex", "1200000"]
            ],
            "total_row_count": 10,
            "status": "available",
            "sql": "SELECT customer, SUM(revenue) AS total FROM sales GROUP BY customer ORDER BY total DESC LIMIT 10"
          }
        },
        {
          "type": "output_text",
          "text": "Acme Corp leads with $1.5M [1](https://host/genie/rooms/01f14fe4e338.../chats/01f14fe4e338...?o=12345&gra_focus=01f14fe4f24e...), followed by Globex at $1.2M [1](https://host/genie/rooms/01f14fe4e338.../chats/01f14fe4e338...?o=12345&gra_focus=01f14fe4f24e...)..."
        }
      ]
    }
  ],
  "first_id": "01f14fe4e34b1b2293908bcece575499_input",
  "last_id": "01f14fe5383f184a97ca1178af0d9356",
  "has_more": false,
  "status": "completed",
  "object": "list"
}

The top-level status field reflects the state of the latest response in the conversation. It is "in_progress" while a response is streaming, and "completed" or "failed" after it finishes. Poll this field to detect when a response has finished.

Pagination

The response includes three pagination fields:

Field Type Description
first_id string The ID of the first item in the current page. Absent when data is empty.
last_id string The ID of the last item in the current page. Pass it as after to fetch the next page. Absent when data is empty.
has_more boolean true when more items follow this page.

To paginate through all items, request pages until has_more is false:

items = []
after = None
while True:
    params = {"limit": 10}
    if after:
        params["after"] = after
    page = client.get(f"/conversations/{conv_id}/items", params=params)
    items.extend(page["data"])
    if not page["has_more"]:
        break
    after = page["last_id"]

The data array contains output items in chronological order. User input messages appear as message items with an _input suffix on the ID.

Understand the response

This section explains how the output items fit together to form a complete Agent mode response.

Output item flow

A typical Agent mode response produces output items in the following order:

reasoning              The agent's plan and analysis
    |
function_call          A SQL query the agent runs
    |
function_call_output   The query results, paired with the function_call above
    |
  ... (reasoning, function_call, and function_call_output repeat for each query) ...
    |
message                The final report, with structured text and inline tables

The agent can run multiple queries in sequence, refining its analysis based on each result. A single response can contain many reasoning, query, and result cycles before the final report.

How function_call and function_call_output pair

Every SQL query produces a pair of output items linked by call_id:

  • function_call is the query the agent runs. The arguments field is a JSON-encoded string that describes the tool invocation.
  • function_call_output is the result. After the item completes, the output field contains the query title followed by a markdown table of the data.

The call_id is identical on both items. The function_call_output.id is always {call_id}_output.

Parse the report

The final output item is a message with role: "assistant". Its content array contains multiple output_text chunks of two kinds:

  • Text chunks hold narrative analysis with inline citation links.
  • Table chunks hold inline query results rendered as markdown tables. Each table chunk carries metadata with the structured query result data, so your client can render rich tables or charts programmatically.

The following table chunk includes both the rendered markdown and the structured metadata:

{
  "type": "output_text",
  "text": "| customer | total |\n| --- | --- |\n| Acme Corp | 1500000 |\n| Globex | 1200000 |",
  "metadata": {
    "columns": [
      { "name": "customer", "type": "STRING" },
      { "name": "total", "type": "DOUBLE" }
    ],
    "preview_rows": [
      ["Acme Corp", "1500000"],
      ["Globex", "1200000"]
    ],
    "total_row_count": 10,
    "status": "available",
    "sql": "SELECT customer, SUM(revenue) AS total FROM sales GROUP BY customer ORDER BY total DESC LIMIT 10"
  }
}

A table chunk metadata object contains the following fields:

Field Type Description
columns array<ColumnInfo> The column definitions.
preview_rows array<array<string>> The truncated result rows.
total_row_count integer The total row count, when known.
status string Either "available" or "fetch_failed".
sql string The SQL query that produced the results.

Citations

Text chunks in the report contain inline citations that link each claim to the SQL query that supports it. Each citation is a markdown link of the form [N](url), where N is a sequential footnote number and url points to the Genie Agent UI with the relevant query focused.

The citation URL has the following format:

https://<workspace-url>/genie/rooms/<space_id>/chats/<conversation_id>?o=<workspace_id>&gra_focus=<attachment_id>

The URL contains the following components:

Component Description
space_id The Genie Agent ID, the same value as agent_id.
conversation_id The conversation that contains the cited query.
workspace_id The numeric workspace ID.
attachment_id The query attachment ID, which identifies the specific SQL query result.

To render citations, follow this guidance based on your client:

  • Markdown renderers display citations as clickable footnote links automatically.
  • For plain text, reduce [N](url) to [N] or remove the citation.
  • For a custom UI, parse the gra_focus query parameter from the URL to identify the cited query, then match it against the function_call_output items in the conversation.

Citations are deduplicated. If the same query is cited multiple times, every reference uses the same index number and URL.

Data models

This section describes the objects that the APIs return.

Response

The Response object is returned in the response.created, response.completed, and response.failed SSE events.

Field Type Description
object string Always "response".
id string The unique response ID.
model string Always "genie-agent".
status string Either "in_progress", "completed", or "failed".
output array<OutputItem> The output items produced by the response.
conversation_id string The conversation the response belongs to.
created_at integer The Unix epoch time in seconds when the response was created.
error ErrorInfo Present when status is "failed".

ErrorInfo

The ErrorInfo object describes a failure:

Field Type Description
type string One of: server_error, invalid_request, not_found, model_error, or too_many_requests.
message string A human-readable description. For internal errors, this is always "An internal error occurred".
code string An optional error code with more detail, such as "sql_execution_error" or "warehouse_access_denied". See Streaming error codes.

Output items

Output items are polymorphic on the type field. The following types are available.

reasoning

The agent's internal reasoning as Agent mode runs.

Field Type Description
type string "reasoning".
id string The unique item ID.
status string Either "in_progress" or "completed".
content array<ContentItem> Contains reasoning_text items.
summary array<string> Always []. Reserved for future use.

function_call

A tool invocation, which is a SQL query execution.

Field Type Description
type string "function_call".
id string The unique item ID.
call_id string The correlation ID that links to the paired function_call_output.
status string "completed".
name string "execute_sql".
arguments string A JSON string, for example {"title": "Human-readable query title", "sql": "SELECT ..."}. The set of keys can change, so your client should not depend on a fixed schema.

function_call_output

The result of a tool invocation, paired with a function_call through call_id.

Field Type Description
type string "function_call_output".
id string Always {call_id}_output.
call_id string Matches the corresponding function_call.
status string Either "in_progress" or "completed".
output string The query result. See the following lifecycle table.

The output field evolves as the item progresses:

Status output contents
in_progress The query title only.
completed The query title, a blank line, then the markdown result table.

Note

Structured query result data, such as columns, rows, and SQL, is available on the report's table chunks, not on the function_call_output item. See Parse the report.

message

A text message. A message appears in one of three roles:

Role When Description
"user" Input The user's question. Appears in GET responses with an _input suffix on the ID.
"assistant" Report The final structured report with text and inline table chunks.
"system" Error or cancel Emitted when a response fails or is cancelled.

The message object contains the following fields:

Field Type Description
type string "message".
role string Either "user", "assistant", or "system".
content array<ContentItem> The message content. See Parse the report for assistant messages.
id string The unique item ID. System messages use {responseId}_error or {responseId}_cancelled.
status string Either "completed", "failed", or "cancelled".

When a response fails, the structured error is delivered on the Response object's error field (see ErrorInfo) and in the response.failed event, not on the system message item.

Content items

The APIs use the following content item types:

Type Fields Used in
input_text text User messages (input).
output_text text, metadata Assistant messages (report chunks). Text chunks contain [N](url) citation links. Table chunks carry metadata with structured query result data.
reasoning_text text Reasoning items.

ColumnInfo

The ColumnInfo object describes a column:

Field Type Description
name string The column name.
type string The column data type, such as "STRING", "DOUBLE", or "BIGINT".

Error handling

The APIs return two kinds of errors: HTTP errors before the stream starts, and streaming errors that end an open stream.

HTTP errors

HTTP errors are returned as standard JSON responses before the SSE stream starts:

{ "error": { "type": "ERROR_CODE", "message": "Human-readable description" } }

The following HTTP errors can occur:

HTTP status Error code Condition
400 INVALID_PARAMETER_VALUE A path parameter is missing, the input items are missing or invalid, or the last input is not a user message.
404 FEATURE_DISABLED The workspace is not enrolled in the preview, or a workspace admin has not turned on the preview.
403 PERMISSION_DENIED The caller lacks CAN VIEW permission on the Genie Agent.
404 NOT_FOUND The Genie Agent or conversation does not exist.
409 RESOURCE_CONFLICT A response is already being generated for the conversation.
500 INTERNAL_ERROR An unexpected server error occurred.

Streaming error codes

When a failure occurs mid-stream, a system error message (role: "system", status: "failed") is emitted as response.output_item.added, followed by the response.failed event. The error object on the Response carries a type and a code.

The type field is one of the following spec types:

type Description
server_error An internal server failure that the client did not cause.
invalid_request A malformed or semantically invalid request, or a permissions issue the user can act on.
not_found A referenced resource does not exist.
model_error The model failed to process an otherwise valid request.
too_many_requests The request was rate limited.

The code field provides more detail:

code type Description
internal_error server_error An unexpected server error. The message is always "An internal error occurred".
sql_execution_error server_error A SQL query failed to execute.
upstream_unavailable server_error An upstream dependency is temporarily unavailable.
timeout server_error The request or an upstream call timed out.
model_unavailable model_error The model is temporarily unavailable.
context_length_exceeded model_error The conversation history exceeded the model's context window.
content_filtered model_error A content filter blocked the response.
rate_limit_exceeded too_many_requests Too many concurrent requests, or an upstream rate limit was reached.
budget_exceeded too_many_requests The workspace exceeded its usage budget for Agent mode.
warehouse_access_denied invalid_request The caller lacks permission to use the configured SQL warehouse.
no_tables_available invalid_request No queryable tables are available in the Genie Agent.
invalid_request invalid_request The request was malformed or missing required fields.
permission_denied invalid_request The caller lost permission, or delegation failed during execution.
conflict invalid_request A concurrent operation conflicted with the request.
warehouse_not_found not_found The configured SQL warehouse does not exist or was deleted.
not_found not_found A referenced resource was not found during execution.

Frequently asked questions

The following questions cover common topics for the Agent mode APIs.

How long do responses take?

Response time depends on the complexity of the question. Single-query questions can complete in under a minute. Multi-query research can take several minutes. The stream has a server-side timeout of 90 minutes.

Can I poll instead of streaming?

Yes. Send the request to create a response, then use the conversation ID from the response.created event to retrieve the conversation items. The items endpoint returns the full conversation history, including in-progress responses. Poll the top-level status field on the items-list response until it is completed or failed.

How does a multi-turn conversation work?

Pass the conversation ID from a previous response in your next request. The agent has access to all prior queries and results in the conversation, and can reference them in the report.

Is the markdown output format stable?

Text content, including report chunks, reasoning text, and query result output, is returned in markdown. The exact markdown structure, such as heading levels and table formatting, is generated by the model and is not guaranteed to be stable across requests or API versions. Treat markdown output as best-effort formatted text, and use the structured fields, such as columns and preview rows, as the stable, machine-readable representation of the data.

Can I retrieve visualizations?

Yes. Retrieve visualizations with the download message attachment visualization endpoint. See GET /api/2.0/genie/spaces/{space_id}/conversations/{conversation_id}/messages/{message_id}/attachments/{attachment_id}/query-result/visualization in the REST API reference.

Do query results expire?

Yes. SQL query results follow the same expiration policy as the Statement Execution API. After results expire, the statement ID no longer returns them. The preview rows in the response metadata remain available from the conversation items endpoint.

How do I know which tables the agent can query?

The agent can only query tables that you add to the Genie Agent. It cannot access your full catalog. For the best results, add column descriptions, sample queries, and join instructions. See Curate an effective Genie Agent.