OPENAI API - BevvyTech/BrewskiDocs GitHub Wiki

============================== OPENAI RESPONSES API OVERVIEW

Base URL: https://api.openai.com/v1/

Authentication: Header: Authorization: Bearer <OPENAI_API_KEY> Header: Content-Type: application/json


ENDPOINTS AND EXAMPLES

  1. CREATE A RESPONSE

POST /v1/responses Purpose: Start or continue a conversation, optionally using tools (functions), and receive the model’s output or tool calls.

Request Example:

{ "model": "gpt-5-mini", "input": [ { "role": "system", "content": [ { "type": "input_text", "text": "You are Brewski Assistant..." } ] }, { "role": "user", "content": [ { "type": "input_text", "text": "Create a new Pale Ale at 4.8% ABV" } ] } ], "tools": [ { "name": "create_beer", "type": "function", "function": { "name": "create_beer", "description": "Create a new beer record", "parameters": { "type": "object", "properties": { "name": { "type": "string" }, "targetAbv": { "type": "number" } }, "required": ["name"] } } }, { "name": "navigate", "type": "function", "function": { "name": "navigate", "description": "Navigate to a route in the Brewski Admin UI", "parameters": { "type": "object", "properties": { "route": { "type": "string", "description": "App path e.g. /orders" } }, "required": ["route"] } } } ], "metadata": { "messageId": "msg_01J83RPV75X42HWN0FKJM8WME8" }, "session_id": "sess_01J83RP3R58ZRWYK13MT30A1SZ", "stream": true }

Response (streamed or final):

Conversation memory

The Responses API is stateless. Every request must include the entire conversation so far (system → user → assistant → user …) plus the tool definitions you want the model to use. To continue a dialogue, resend all previous turns along with the new message:

{
  "model": "gpt-5-mini",
  "stream": true,
  "tools": [create_beer_schema, navigate_schema],
  "input": [
    {"role":"system","content":[{"type":"input_text","text":"You are Brewski Assistant."}]},
    {"role":"user","content":[{"type":"input_text","text":"start a brew"}]},
    {"role":"assistant","content":[{"type":"output_text","text":"I couldn't find any beers matching 'brew'. Tell me the exact beer name..."}]},
    {"role":"user","content":[{"type":"input_text","text":"Sombrero"}]}
  ]
}

If you omit the earlier turns, the model has no context for the new input and is likely to return “Model returned no output.” Likewise, always resend the tool schemas on every call so the model knows which functions it can invoke.

{ "id": "resp_abc123", "output_text": { "text": "✅ Created Pale Ale (4.8% ABV)." }, "output_tool_calls": [ { "tool_call_id": "call_01J83RP5...", "name": "create_beer", "arguments": "{"name":"Pale Ale","targetAbv":4.8}" } ], "usage": { "input_tokens": 1200, "output_tokens": 200 }, "status": "completed" }

  1. SUBMIT TOOL OUTPUTS

POST /v1/responses/submit_tool_outputs Purpose: Send back the results of any tool calls so the model can continue.

Example:

{ "response_id": "resp_abc123", "tool_outputs": [ { "tool_call_id": "call_01J83RP5...", "output": "{ "id": "beer_42", "name": "Pale Ale", "abv": 4.8 }" } ] }

Response:

{ "id": "resp_abc123", "status": "completed", "output_text": { "text": "✅ Beer created successfully." } }

  1. RETRIEVE A RESPONSE

GET /v1/responses/{response_id} Purpose: Retrieve a completed or partial response by ID.

Example: GET /v1/responses/resp_abc123

Response:

{ "id": "resp_abc123", "status": "completed", "output_text": { "text": "✅ Beer created successfully." }, "output_tool_calls": [], "usage": { "input_tokens": 1342, "output_tokens": 418, "total_tokens": 1760 } }

  1. CREATE EMBEDDINGS

POST /v1/embeddings Purpose: Convert text into numerical vectors for document search / RAG.

Example:

{ "model": "text-embedding-3-small", "input": ["When packaging cans, double-check BBE dates..."] }

Response:

{ "data": [ { "embedding": [0.0123, 0.9834, -0.4578, ...] } ], "usage": { "prompt_tokens": 34, "total_tokens": 34 } }


STREAMING OUTPUTS

If "stream": true in the request, the server sends Server-Sent Events (SSE):

data: {"type":"output_text.delta","delta":"Cre"} data: {"type":"output_text.delta","delta":"ating new Pale Ale..."} data: {"type":"output_tool_calls","tool_call":{...}} data: {"type":"completed"}

  • The Brewski API watches response.message.delta, response.output_text.delta, and response.completed events so the assistant always returns a visible reply, even when OpenAI skips incremental chunks.
  • Nested tool_call(s) payloads are normalised before they reach the frontend, keeping start_ui_flow and other function calls aligned with their expected arguments.

EXPECTED NAVIGATION EXAMPLE

When a user says "open orders", the model should respond with a tool call to your navigate tool:

{ "output_tool_calls": [ { "tool_call_id": "call_12345", "name": "navigate", "arguments": "{"route":"/orders"}" } ] }

Your backend should then forward this to the frontend (via WebSocket):

{ "type": "action", "action": { "type": "navigate", "route": "/orders" } }

The frontend executes: navigate("/orders")


ISSUE DESCRIPTION (WHAT HAPPENED LAST TIME)

Last time, the log looked like this:

[02:58] OUT · send { "type": "message", "text": "open orders" } [02:58] IN · message {"type":"status","status":"processing","messageId":"1eb52703-2b72-4095-9ebe-655fc7f30502"} [02:58] IN · message {"type":"complete","messageId":"07396230-8461-4c54-aec6-c2cfe99f48dc","text":"","usage":{"input_tokens":1839,"output_tokens":10,"total_tokens":1849}} [02:58] IN · message {"type":"ack","messageId":"1eb52703-2b72-4095-9ebe-655fc7f30502","enqueued":true} [02:58] IN · message {"type":"echo","messageId":"1eb52703-2b72-4095-9ebe-655fc7f30502","text":"open orders"}

Interpretation:

  • The model accepted the request ("status":"processing")
  • It completed with an empty text field ("text": "")
  • No "output_tool_calls" appeared in the stream
  • No "navigate" action or tool event was emitted

Therefore: → The model did not call any tool. → No navigation instruction was issued. → The assistant produced an empty output.

Probable causes:

  1. The navigate tool was missing from your tools array in that call.
  2. The system prompt did not instruct the model to use navigate for page requests.
  3. Your stream handler only logged text deltas and ignored tool call events.
  4. A parser or validation step dropped the output_tool_calls field.

To fix:

  • Ensure the navigate tool is registered in tools every turn.
  • Add to system prompt: "If a user asks to open or view a page, call navigate with the correct route."
  • Log and handle all stream event types (output_text, output_tool_calls, completed).

Expected working example output:

{ "type": "action", "action": { "type": "navigate", "route": "/orders" } } or "output_tool_calls":[{"name":"navigate","arguments":"{"route":"/orders"}"}]