Skip to main content
Version: Latest (1.1.x dev)

Function Calling (Tools)

DVARA relays OpenAI-compatible function calling through POST /v1/chat/completions. Clients send tools and tool_choice, the gateway forwards them to the selected provider in that provider's native shape, and the model's tool_calls are relayed back to the client unchanged.

The gateway is a governed passthrough, not an agent. DVARA does not execute tools and runs no agent loop — your application runs the tool and sends the result back on the next turn, exactly as it would talking to OpenAI directly. What DVARA adds is governance: tool-call arguments flow through the same PII and guardrail scanning as ordinary message content (see Governance below).

Request shape

Send tools and (optionally) tool_choice alongside your messages. All fields use the OpenAI schema:

{
"model": "gpt-4o",
"messages": [
{ "role": "user", "content": "What's the weather in Paris?" }
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city",
"parameters": {
"type": "object",
"properties": { "city": { "type": "string" } },
"required": ["city"]
}
}
}
],
"tool_choice": "auto"
}

Only function-typed tools are relayed. Entries of other shapes (e.g. hosted/built-in tools) are skipped rather than forwarded.

Response shape

When the model decides to call a tool, DVARA returns the tool calls on the assistant message with finish_reason: "tool_calls":

{
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_1",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\":\"Paris\"}"
}
}
]
},
"finish_reason": "tool_calls"
}
]
}

function.arguments is a JSON string the model produced (parse it yourself), exactly as OpenAI returns it.

Completing the round trip

Function calling is a multi-turn exchange your client drives:

  1. Send the request with tools.
  2. Receive tool_calls + finish_reason: "tool_calls".
  3. Execute the tool yourself and append two messages to the history: the assistant message carrying the tool_calls, then a tool message with the result:
{ "role": "tool", "tool_call_id": "call_1", "content": "sunny, 24°C" }
  1. Call /v1/chat/completions again with the extended history. The model now answers using the tool result.

Provider support

Function calling only works on providers that advertise the tool-calling capability. When a request carries tools, DVARA filters routing to providers whose capability includes tool calls; if no capable provider is available on the route, the request is rejected rather than silently sent to a provider that would ignore the tools.

Check which models support tool calls via GET /v1/models — each entry carries a supports_tool_calls flag (also exposed on the per-provider capabilities endpoint). Provider-native translation is handled for you: OpenAI-compatible providers receive the tools shape above, while Anthropic-family providers receive the equivalent tool_use / tool_result translation.

Streaming limitation

Tool calls are not surfaced on streaming responses. With stream: true, DVARA normalizes every upstream chunk to a content delta on the wire — native tool-call deltas do not carry through, and the client sees empty content deltas with a finish_reason: tool_calls.

Use non-streaming (stream: false, the default) when your client needs to consume tool calls. See Streaming for the full detail on how chunks are normalized.

Governance

Tool-call content is governed like any other request content — this is the point of routing function calling through the gateway rather than calling the provider directly:

  • tool_calls[].arguments (the raw JSON the model produced, replayed as assistant history on the next turn) are scanned by both PII detection and the guardrail detectors on the request path.
  • Tool results ({"role": "tool", ...} messages) are scanned as ordinary message content.

So an injection or PII payload smuggled into a tool call's arguments is subject to the same BLOCK / REDACT / FLAG / LOG actions as one in a user message.

Not yet supported

  • Streaming tool-call deltas — non-streaming only today (see above).
  • Function calling on /v1/responses — this feature is on /v1/chat/completions. The /v1/responses endpoint rejects tool requests cleanly (it does not silently drop them); function calling there is a planned follow-up.
  • Hosted / built-in tools (web search, file search, code interpreter, computer use, remote MCP) — DVARA relays your own function definitions only. For MCP tool governance, use the DVARA MCP Proxy.