Skip to main content
POST /v1/chat/completions accepts the standard OpenAI tools array. The model emits structured tool_calls in its response when it decides a tool is the right move; your code runs the tool and round-trips the result back as a role: "tool" message.

Tool schema

Each tool is a function declaration with a JSON-schema parameter object:
{
  "type": "function",
  "function": {
    "name": "get_weather",
    "description": "Return the current weather for a city.",
    "parameters": {
      "type": "object",
      "properties": {
        "city": { "type": "string", "description": "City name, e.g. 'Berlin'." },
        "unit": { "type": "string", "enum": ["c", "f"], "default": "c" }
      },
      "required": ["city"]
    }
  }
}
The tool_choice field controls how the model picks a tool:
ValueBehavior
"auto" (default if tools is set)Model decides per turn whether to call a tool.
"none"Disable tool calls for this turn.
"required"Force the model to call at least one tool. Returns 400 tool_choice_required_unsupported if the model lacks the capability.
{ "type": "function", "function": { "name": "..." } }Force a specific tool.

Single-turn example

curl -X POST https://api.aurous-labs.com/v1/chat/completions \
  -H "Authorization: Bearer $AUROUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "aurous-grow-2.0-pro",
    "messages": [
      { "role": "user", "content": "What is the weather in Berlin?" }
    ],
    "tools": [
      {
        "type": "function",
        "function": {
          "name": "get_weather",
          "description": "Return the current weather for a city.",
          "parameters": {
            "type": "object",
            "properties": {
              "city": { "type": "string" },
              "unit": { "type": "string", "enum": ["c", "f"] }
            },
            "required": ["city"]
          }
        }
      }
    ],
    "tool_choice": "auto",
    "max_tokens": 512
  }'

Round-tripping the tool result

After the model emits a tool call, run the tool locally, then re-call chat.completions.create with the original assistant message AND a new role: "tool" message carrying the result:
Node.js (OpenAI SDK)
// Step 1: model returned a tool_call.
const assistantMessage = first.choices[0].message;
const call = assistantMessage.tool_calls![0];
const args = JSON.parse(call.function.arguments);

// Step 2: run the tool (your code).
const weather = await fetchWeather(args.city, args.unit);
//   → { tempC: 14, condition: "cloudy" }

// Step 3: send the tool result back as a follow-up turn.
const followup = await client.chat.completions.create({
  model: "aurous-grow-2.0-pro",
  messages: [
    { role: "user", content: "What is the weather in Berlin?" },
    assistantMessage, // contains tool_calls
    {
      role: "tool",
      tool_call_id: call.id,
      content: JSON.stringify(weather),
    },
  ],
  max_tokens: 512,
});

console.log(followup.choices[0].message.content);
// → "It's 14°C and cloudy in Berlin right now."
The tool_call_id on the role: "tool" message must match the id field on the assistant’s tool_calls entry. The model may emit multiple tool calls in a single turn — round-trip them all in one follow-up.

Parallel tool calls

If the model emits two or more tool calls in a single turn (message.tool_calls.length > 1), run them in parallel and send all results back in the next request:
const calls = assistantMessage.tool_calls!;
const results = await Promise.all(
  calls.map(async (c) => ({
    role: "tool" as const,
    tool_call_id: c.id,
    content: JSON.stringify(await dispatchTool(c.function.name, c.function.arguments)),
  })),
);

const final = await client.chat.completions.create({
  model: "aurous-grow-2.0-pro",
  messages: [
    { role: "user", content: "Compare Berlin and Tokyo weather." },
    assistantMessage,
    ...results, // one tool message per call
  ],
});

Forcing a specific tool

Pin the tool the model must call by name:
{
  "tools": [...],
  "tool_choice": {
    "type": "function",
    "function": { "name": "get_weather" }
  }
}
Combined with response_format, this is the building block for “extract structured data from text” flows: define a tool whose parameters match the schema you want and force it.

Streaming and tools

When stream: true, tool-call arguments arrive as delta.tool_calls[*].function.arguments fragments that you must concatenate per id until you see finish_reason: "tool_calls". The OpenAI Node and Python SDKs both expose tool_calls accumulators on their streaming helpers — prefer those over hand-parsing deltas.

Errors

  • tool_choice_required_unsupported (400) — you passed tool_choice: "required" to a model whose aurous_metadata.capabilities doesn’t include tool_choice_required. List models via GET /v1/models to check capability flags before setting this.
  • response_format_too_large (400) — the JSON schema in response_format exceeds the platform’s payload cap. Trim the schema (fewer properties, shorter descriptions) and retry.
  • response_format_too_deep (400) — the JSON schema nests deeper than the parser’s cap. Flatten nested definitions or pull them into $defs references.