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
- 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" }
- 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." } }
- 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 } }
- 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, andresponse.completedevents 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, keepingstart_ui_flowand 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:
- The
navigatetool was missing from yourtoolsarray in that call. - The system prompt did not instruct the model to use
navigatefor page requests. - Your stream handler only logged
textdeltas and ignored tool call events. - A parser or validation step dropped the
output_tool_callsfield.
To fix:
- Ensure the
navigatetool is registered intoolsevery turn. - Add to system prompt: "If a user asks to open or view a page, call
navigatewith 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"}"}]