Skip to main content
This tutorial walks you through building on Direct Responses, POST /ai/v2/direct/responses, one step at a time. Want the concepts first? Read the Direct Responses guide. For every parameter and response field, see the Direct Responses API reference.
Why Direct Responses? It sends your request straight to the model you name, with one request and response shape across every provider, and it bills the model’s published rate. It takes the same request body as the guarded Responses endpoint. Choose Direct Responses when you want the provider’s model as-is and handle safety yourself, and guarded Responses when you want Gloo’s guardrails and values alignment built in. See Which endpoint should I use?

Prerequisites

Before starting, make sure you have:
  • A Gloo AI Studio account
  • Your API key from the API Keys page, exported as GLOO_API_KEY
  • Authentication setup: complete the Authentication Tutorial first
  • Python 3.9+ with requests (pip install requests), or Node.js 18+ (for built-in fetch)

What You’ll Build

A small command-line assistant, built up in five steps:
  1. First request: send a prompt and read the typed output[] array
  2. Choose a model: list the catalog and pick a model ID
  3. Stream: print the answer as it is generated
  4. Multi-turn: keep a conversation going with instructions and history
  5. Tool call: let the model call a function you define, then answer with its result
Then you’ll add error handling and put it all together in Complete Code.

Step 1: Your First Request

Send a model and an input. input can be a plain string or an array of {role, content} items.
On a reasoning model, max_output_tokens holds the model’s thinking as well as its answer, and Responses sends it as you set it. The examples here set 4,096 to leave room for both. See Set your output limit for reasoning models.

Understanding the Response

The answer arrives as a typed output[] array. Plain text comes back as a message item whose content[] holds output_text parts:
Other item types share the same array: a reasoning summary arrives as a reasoning item, a tool call as a function_call item (Step 5) and a generated image as an image_generation_call item. Walking output[] by type, as output_text does, keeps your code working whichever items come back.
Already using the OpenAI SDKs? Point the base URL at https://platform.ai.gloo.com/ai/v2/direct and call responses.create. This tutorial uses plain HTTP so every field is visible.

Step 2: Choose a Model

Direct Responses calls exactly the model you name, so the model ID is your main choice. The live catalog is at GET /platform/v2/models, which needs no authentication. Each entry has an id to use as model, plus capability flags such as supports_tools, supports_streaming and supports_reasoning, a context_window (the context window: how much input the model can take), list pricing, and is_deprecated. List the models that can stream and call tools, and aren’t being retired:
What to weigh when you pick:
  • Capabilities. Steps 3 and 5 need supports_streaming and supports_tools. Image input needs a vision-capable model (supports_vision).
  • Cost. You pay the model’s published rate per token, with nothing added on direct endpoints. See Pricing and token spend.
  • Reasoning. Models with supports_reasoning can think before answering; set reasoning.effort to control how much. See Reasoning and the Models That Think lesson.
  • Deprecations. A deprecated model lists a replacement_model. See Model Lifecycle.
This tutorial keeps gloo-anthropic-claude-sonnet-4.6 in one MODEL constant, so trying another model is a one-line change. The Supported Models page shows the same catalog as a table.

Step 3: Stream the Answer

Set "stream": true to stream the answer as Server-Sent Events. Each event is an event: line followed by a data: line with a JSON payload. Three event types carry what you need: Other events (response.output_item.added, response.content_part.done and so on) mark structure and can be ignored for plain text. The final event’s shape depends on the model. For OpenAI models its fields sit under a response key; for other models they’re at the top level, without output[]. Read data.response when present and fall back to data, and build the answer from the deltas.
A stream can fail after text is already on screen. Keep the partial text rather than erasing it, and don’t silently start over. See Handling Streaming Failures for when to retry, when to offer Continue, and retry ceilings.

Step 4: Hold a Multi-Turn Conversation

Use instructions for the system prompt and send the whole conversation in input on every request. Conversation state lives in your application: previous_response_id and conversation (server-side chaining) are not supported.
The history grows with every turn and is billed as input tokens each time, so long conversations cost more and eventually approach the model’s context window. Trim or summarize older turns once they stop being useful.
You can also send output[] items back exactly as you received them, which is how tool calls work in the next step. On a reasoning model, a reasoning item you send back is not carried into the next request: each request is reasoned afresh from the conversation in input. See Reasoning across turns.

Step 5: Let the Model Call a Function

Tool use lets the model ask your code for information it doesn’t have. The round trip has three parts:
  1. Send tools with your request. The model answers with a function_call item naming the function and its JSON arguments.
  2. Run the function yourself.
  3. Send the conversation again with the model’s function_call and a function_call_output holding your result under the same call_id. The model then answers as a normal message.
Define tools with the nested function schema, {"type": "function", "function": { ... }}, the same schema Completions V2 uses. See Tool Use.
The model’s first answer contains a function_call item like this:
arguments is a JSON string written by the model, so treat it like any other untrusted input: run_tool parses it, picks out only the campus field it expects, and sends an error result back to the model instead of crashing when the arguments don’t fit. To make the model call a tool rather than answer directly, send "tool_choice": "required".

Step 6: Handle Errors

Direct Responses errors follow the direct endpoint error contract. Every error carries:
  • a short message that is safe to show your users as is
  • a developer_message and retryable flag for you
  • an X-Gloo-Error-Code header with a stable lowercase code to branch on, and an X-Request-Id to include when you contact support
  • a Retry-After header on errors where Gloo knows how long to wait
The fields sit under error for provider and platform failures and under detail for refusals such as authentication or content policy. Read whichever is present, and never parse the wording of message: it can change, the codes don’t.
create follows the retry rule for a request someone is waiting on: it retries only errors marked retryable and network failures with no response, at most twice, with waits of 2 seconds or less. When Retry-After asks for longer, such as the 30 seconds a 503 can ask for, it raises at once so you can show message instead of leaving the terminal silent. A Retry-After that isn’t a number of seconds falls back to backoff. For a batch job nobody is watching, raise the budget to 5 requests in total and the wait cap to 30 seconds. The same rules apply to a stream that fails before any output: it returns a normal HTTP status and body. A stream that fails after output has started ends with response.failed, whose response.error carries the string code, message, retryable and developer_message. For retry ceilings and partial-output handling, see Handling Streaming Failures.

Complete Code

To run every step from one file, start with the imports and constants below, then paste in the functions you already wrote. Copy only the definitions, not each step’s example calls, and use Step 6’s retrying create in place of Step 5’s simpler one. Finish with main(), export GLOO_API_KEY, and run it.

Troubleshooting

401 with X-Gloo-Error-Code: authentication_error : The API key is missing, invalid or expired. Check that GLOO_API_KEY is exported in the shell that runs the script, and that the header reads Authorization: Bearer <key>. 400 naming an unknown model : The model ID isn’t in the catalog. Copy an id from GET /platform/v2/models (Step 2). The answer stops early, or status is "incomplete" : The response reached max_output_tokens. On a reasoning model the thinking counts toward that limit too. Raise max_output_tokens or lower reasoning.effort; see Set your output limit for reasoning models. The streaming loop prints nothing : Match on the event: line (or the payload’s type), and read text only from response.output_text.delta. Don’t wait for output[] on the final event: for non-OpenAI models, response.completed has no output[]. The model never returns a function_call : Check that the tool uses the nested {"type": "function", "function": {...}} schema and that the model has supports_tools in the catalog. To require a call, send "tool_choice": "required". 400 mentioning function calling or tools : The model takes no tools, for example a Gemini image model. Remove tools, or pick a model with supports_tools. The second tool request fails or ignores the result : The function_call and function_call_output items need the same call_id, the call_id from the model’s function_call item. output must be a string, so JSON.stringify / json.dumps your result. A parameter seems to have no effect : Some models don’t take every sampling parameter (for example temperature on some reasoning models). The request still succeeds, and the parameters that weren’t applied are listed in the response’s ignored_params.

Next Steps

Direct Responses guide

Reasoning summaries, vision, image generation and pricing

Direct Responses API reference

Every request parameter and response field

Handling Streaming Failures

Retry ceilings, continuation and partial-output UX

Grounded Responses tutorial

Answer from your own content with the same request shape

Guarded Responses tutorial

The same body with Gloo’s guardrails and values-alignment

Tool Use

Tool schemas, tool results and tool use on Completions V2