Function Tools函数工具(Tool Calling)

Build agentic workflows with OpenAI-compatible tool calling — entirely on-device. Both the Foundry Local and ORT engines support the OpenAI tools + tool_choice interface.使用 OpenAI 兼容的工具调用接口构建 Agentic 工作流——完全在设备上运行。Foundry Local 和 ORT 引擎均支持 OpenAI tools + tool_choice 接口。

How It Works工作原理

Engine引擎 Strategy策略
Foundry Local Tools forwarded natively via the standard OpenAI tools parameter. Response may carry native tool_calls or functools[...] format — both normalised automatically.工具定义通过标准 OpenAI tools 参数原生转发。响应可能携带原生 tool_calls 字段或 functools[...] 格式——两种格式均自动归一化。
ORT Tools serialised as JSON Schema inside the system prompt. Model replies with a <tool_call>{...}</tool_call> block; parse_tool_call() extracts and validates it.工具以 JSON Schema 形式注入系统提示词。模型以 <tool_call>{...}</tool_call> 块回复,parse_tool_call() 负责提取和验证。

Both engines return the same ChatResponse structure — your application code is engine-agnostic.两个引擎返回相同的 ChatResponse 结构——你的应用代码与引擎无关。

Supported Output Formats (auto-detected)支持的输出格式(自动检测)

Format格式 Example示例
<tool_call> block<tool_call>{"name": "get_weather", "arguments": {"city": "Paris"}}</tool_call>
Phi-3 native<|function_calls|>{...}<|/function_calls|>
Mistral-style<functioncall>{...}</functioncall>
Markdown code block```json {...} ```
OpenAI-legacy wrapper{"function_call": {"name": ..., "arguments": ...}}
Bare JSON{"name": "...", "arguments": {...}}

Example: Two-turn Tool-Calling Agent示例:两轮工具调用 Agent

This example demonstrates a complete tool-calling workflow: the model decides to call a function, your code executes it, then the model generates a final response using the tool result.此示例演示完整的工具调用工作流:模型决定调用函数,你的代码执行该函数,然后模型使用工具返回的结果生成最终响应。

Step 1: Start the server第 1 步:启动服务

bash
obeaver serve Phi-4-mini

Step 2: Python client with tool calling第 2 步:Python 客户端调用工具

python
from openai import OpenAI
import json

client = OpenAI(base_url="http://127.0.0.1:18000/v1", api_key="unused")

# Define tools
tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get current weather for a city",
        "parameters": {
            "type": "object",
            "properties": {"city": {"type": "string"}},
            "required": ["city"],
        },
    },
}]

messages = [{"role": "user", "content": "What is the weather in Tokyo?"}]

# Turn 1 — model decides to call a tool
resp = client.chat.completions.create(
    model="Phi-4-mini",
    messages=messages,
    tools=tools
)
choice = resp.choices[0]

if choice.finish_reason == "tool_calls":
    tool_call = choice.message.tool_calls[0]
    args = json.loads(tool_call.function.arguments)

    # Execute your function (replace with real implementation)
    weather_result = {"city": args["city"], "temperature": "18°C", "condition": "Sunny"}

    # Turn 2 — send tool result back to model
    messages += [
        choice.message,
        {"role": "tool", "tool_call_id": tool_call.id, "content": json.dumps(weather_result)},
    ]
    final = client.chat.completions.create(
        model="Phi-4-mini",
        messages=messages
    )
    print(final.choices[0].message.content)

curl Examplescurl 示例

Foundry Local

bash
obeaver serve Phi-4-mini
curl -s http://127.0.0.1:18000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d @tests/tool_foundrylocal_request.json

ORT

bash
obeaver serve --engine ort ./models/Qwen3-0.6B_ONNX_INT4_CPU
curl -s http://127.0.0.1:18000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d @tests/tool_ort_request.json

Tool-Calling Internals工具调用内部实现

Component组件 Role作用
ToolCallDataclass: id, name, arguments.to_openai_dict()数据类:idnamearguments.to_openai_dict()
ChatResponseUnified engine response: content, tool_calls, finish_reason引擎统一响应结构:contenttool_callsfinish_reason
inject_tools_into_messages()Appends JSON Schema tool definitions to system prompt (ORT path)将 JSON Schema 工具定义追加到系统提示词(ORT 路径)
parse_tool_call()Extracts ToolCall from raw model output; handles 6 format variants从模型原始输出中提取 ToolCall;处理 6 种格式变体
build_tool_result_message()Builds the role: tool message for turn-2 follow-up构建第二轮对话中发回的 role: tool 消息

Data Flow数据流

text
User request + tools
  → inject_tools_into_messages() [ORT] / pass tools natively [Foundry]
  → Engine generates response
  → parse_tool_call() extracts ToolCall
  → Application executes the function
  → build_tool_result_message() creates turn-2 message
  → Engine generates final response with tool result context