The OpenAI tool-call body on a self-hosted chat endpoint
What a tools array looks like in a chat request, and what this host does with it.
A client that wants tool use adds a tools array to POST /v1/chat/completions. Each entry has a type of function and a function object with a name, a description, and a JSON schema under parameters. The message list is unchanged. GET /v1/tools on this host lists the published names, covering search, reference, numbers, code, files, mail, calendar, maps, media, and machine status. A client can send one of those, or a name of its own.
Whether the server answers with tool_calls is a separate choice from whether it accepts the body. This host accepts the body on the OpenAI-compatible ports and replies with an ordinary assistant message, finish_reason of stop. The message names the function names from that array. It does not emit tool calls from the chat route.
A follow-up uses the same path. Add a message with role tool, a tool_call_id, and the result string in content. The next assistant message acknowledges that result.
A separate route on the OpenClaw port takes a tool invocation as its own request. That is POST /tools/invoke on port 18789, with a JSON object, and no API key. The chat ports and that route are not the same call.
On this host
Send the tools array to port 8000 if you want to see the chat response. Send an invocation to port 18789 if you want the tool route. Neither requires a key.
curl http://datattention.com:8000/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"What time is it?"}],"tools":[{"type":"function","function":{"name":"now","description":"Current time","parameters":{"type":"object","properties":{}}}}]}'
curl http://datattention.com:18789/tools/invoke \
-H 'Content-Type: application/json' \
-d '{"tool":"now","args":{}}'
The full list of ports and paths is on the endpoints page.