Skip to main content
The agents endpoints follow OpenAI’s Responses API, so OpenAI’s SDKs work as they are: point the client at https://api.qxlabs.com/v1 with your QX API key and call responses.create. model names the agent, builtin:qx_agent for the QX agent or an agent’s ID from its URL in the app. Each snippet below has cURL, Python and TypeScript tabs, and each one runs as it is once your key replaces <YOUR_QX_API_KEY>.

Set up the client

Install the SDK with pip install openai or npm install openai, then create a client with your key. With cURL there’s nothing to set up: every call sends the key as a bearer token.

Send a message

A message is one call. The reply’s text is in output_text, and output holds everything the agent did: its thinking as reasoning items, each tool call as an mcp_call item, and its message. To send a file, make the message a list with input_text and input_file parts, with the file as a base64 data URL.

Continue a conversation

Send the last response’s id as previous_response_id, or the conversation’s ID as conversation. Either one keeps the whole conversation, which you can also open in the app’s chat. A message with neither starts a new conversation.

Stream the reply

Set stream to true to get the Responses API’s events as they happen, or use the SDK’s stream helper, which also gives you the final response. A call without streaming must finish within 240 seconds, so stream anything long. To stop an agent while it works, cancel any response of its conversation. What the agent already did stays.

Approvals

Some tools need approval before they run, like sending an email. permission_mode decides what happens, for that message only: delegated (the default) refuses the tool, normal makes the agent ask first, and auto lets it run. It’s QX’s own field, so Python sends it in extra_body and TypeScript needs a type that allows it. In normal mode the response ends with mcp_approval_request items, each with the call’s arguments and the agent’s reason. Answer with mcp_approval_response items in input, on the same conversation and with no message, and the turn carries on. Each answer covers its one call.

Choose an app account

When you have more than one account for an app, like two Gmail accounts, the agent uses the app’s default. To use another one, send connected_accounts with the app and the account’s ID. The connected accounts endpoint lists yours. It’s a QX endpoint, so the SDKs read it with their own get.

Read the history

conversations.items.list returns a conversation’s messages and tool calls, newest first. limit counts turns, a user message and everything after it, and the SDKs fetch the next pages as you go.

Good to know

  • Tool calls come back as mcp_call items. A call to one of QX’s own tools shows only the command, search words, URL or path it was given, a call to an app’s tool shows no arguments, and output is always null. A failed call has its reason in error.
  • The agent’s thinking comes as reasoning items, and its tokens are in usage.output_tokens_details.reasoning_tokens.
  • A message sent while the conversation is still answering the last one joins that turn, and the response carries steered: true.
  • Errors come in OpenAI’s shape, so the SDKs raise their usual errors. An org out of credits gets a 429 with code insufficient_quota before any stream starts. The SDKs don’t resend a message that failed, because the API asks them not to.