Here's the complete implementation: send request → parse streaming → detect function_call → execute → send result → repeat.
The same loop, your wiring
The conceptual loop is identical to the SDK version: build request → POST → parse response → if tool_calls execute and append → POST again → else return text. The difference is that every step is yours to instrument. You can log the raw request body, the raw response body, the parsed tool_call decisions, the handler return values — at any point, with no SDK helper hiding the shape.
This level of control is overkill for typical product code; it's exactly right when building an adapter that has to support multiple providers, when reproducing a customer bug from a captured wire trace, or when integrating with an LLM gateway that expects you to behave like a well-behaved HTTP client.