| title | Function Calling |
|---|---|
| description | Use function calling and tool use with DOAI Proxy, including providers without native support. |
DOAI Proxy supports function calling even when the underlying provider doesn't support it natively. For providers without native function calling (like Straico), the proxy uses prompt injection to enable tool use.
For providers without native function calling:
- Request Processing: Proxy detects if request includes
toolsparameter - Tool Injection: Converts tool definitions into system prompt instructions via
injectToolsIntoSystem() - Prompt Formatting: Tells AI to use format:
TOOL_CALL: name\nARGUMENTS: {json} - Response Parsing:
parseToolCall()checks AI response for tool call patterns using 4 parsers - Tool Call Detection: Extracts tool name and arguments from response
- Response Formatting: Returns tool call object with
finish_reason: 'tool_calls' - Multi-turn Support: Client can execute tool and send result back as
role: 'tool'message
{
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": { "type": "string", "description": "City name" }
},
"required": ["location"]
}
}
}
]
}When the AI decides to use a tool, it responds in this text format:
I can help you check the weather. Let me get that information for you.
TOOL_CALL: get_weather
ARGUMENTS: {"location": "Tokyo"}
The proxy parses this and returns a proper OpenAI tool call object:
{
"id": "call_1234567890",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"location\":\"Tokyo\"}"
}
}With finish_reason: "tool_calls".
parseToolCall() tries four parsers in order. The first non-empty result wins:
- Minimax XML (
parseMinimaxXML): Matches<minimax:tool_call><invoke ...>with attribute-style or<parameter>children - Claude XML (
parseClaudeXML): Matches<invoke name="..."><parameter_list><parameter name="...">...</parameter></parameter_list></invoke> - OpenAI Native (
parseOpenAIToolCalls): Looks for"tool_calls": [...]JSON fragments inside response text - Text Format (
parseTextFormat): MatchesTOOL_CALL: <name>\nARGUMENTS: {json}
Parsed tool calls are validated against the client-provided tool list. Unknown tool names are filtered.
The proxy normalizes messages for compatibility:
| Input Form | Transformation |
|---|---|
Array content (multimodal) |
Joined to plain text; <system-reminder> blocks stripped |
role: "tool" messages |
Converted to role: "user" with [Tool Result]: prefix, or dropped |
role: "assistant" with tool_calls |
Serialized to TOOL_CALL: <name>\nARGUMENTS: <json> text |
| Empty assistant messages | Dropped to avoid provider API errors |
When TOOL_RESULT_MAX_LENGTH is set, tool result messages longer than the limit are truncated. Set to -1 or leave unset to disable truncation.
- Format dependency: AI must follow exact format for tool calls to be detected (for providers without native support)
- Prompt-instructed single call: The system prompt instructs the AI to make one tool call at a time, though the parser can handle multiple sequential calls
- No tool execution: Proxy doesn't execute tools, just formats tool call objects
- Requires AI compliance: If AI doesn't follow format, tool calls won't be detected
- Multi-turn conversations with tools: Currently only one turn (user → tool → assistant) is supported
- Large tool definitions: Very large tool schemas may not fit in provider's context window
- Function Calling Examples — complete working examples of function calling
- API Endpoints — reference for available API endpoints