Model inference
Model inference runs the tauric model on your own messages, instructions, and function tools, in OpenAI's wire
format. Your messages and tools reach the model unchanged: the API adds no instructions, tools, or data lookup. A tool call the model
chooses is returned for you to execute. Requests are stateless, and nothing is stored. The answer is model output, so
it makes no coverage, freshness, or provenance claim. For answers from the stored data, use the copilot;
for a full company report, use research.
Routes
| task | route | entitlement |
|---|---|---|
| list the model, or read it | GET /v1/models, GET /v1/models/tauric | data (the data pool) |
| Chat Completions | POST /v1/chat/completions | ai (the AI pool) |
| Responses | POST /v1/responses | ai (the AI pool) |
Entitlements come with your tier (entitlements); a first call is in Python examples.
The model
The one public model is tauric; GET /v1/models/tauric returns it, and any other id is 404 model_not_found. A
request may omit model. Any value other than tauric is refused 400 model_not_found.
Limits
| limit | value |
|---|---|
| output tokens when you send no limit | 16,384 |
| the largest output limit you may send | 32,768 (max_completion_tokens, max_tokens, or max_output_tokens) |
| context window: input, tools, and output together | 262,144 tokens |
| time to finish one request | 15 minutes |
A request body is at most 1 MiB. The output limit counts everything the model generates and is an upper bound. A limit above
the largest is refused 400 invalid_request naming the field. A request whose input plus output limit does not fit the
context window is refused 400 context_length_exceeded. A refused request answers its HTTP error, streamed or not,
before any stream opens, and costs nothing.
An answer that stops at its output limit ends with finish_reason: length (Chat) or
incomplete_details.reason: max_output_tokens (Responses). One that runs out of time is 504 timeout, or, once a
stream has started, ends with a server_error event.
Compatibility
Requests use OpenAI's Chat Completions and Responses formats. What is supported:
| supported | detail |
|---|---|
| Chat Completions and Responses, streamed or not | POST /v1/chat/completions, POST /v1/responses |
| function tools | at most 128, type function, each name 1–64 characters of [A-Za-z0-9_-]; the model returns a call and you execute it |
| text in and out | content is text; structured output with json_object or json_schema |
| sampling | temperature and top_p; on Chat Completions also seed, stop, presence_penalty, frequency_penalty |
| stateless requests | send the whole conversation each time, at most 512 messages or items; store is false only |
Any other field, a non-text content part, a tool whose type is not function, and an Idempotency-Key header are
refused 400 unsupported_parameter, with param naming the field. Every field is described in the
API reference.
Chat Completions
POST /v1/chat/completions takes messages, and optionally tools, tool_choice, parallel_tool_calls, the sampling fields, the output
limit (max_completion_tokens, or its alias max_tokens; if you send both they must agree; limits),
response_format, and stream with stream_options: {"include_usage": true}. n is 1 only.
A message has the role system, developer, user, assistant, or tool. An assistant message carries
tool_calls when the model called a tool; a tool message carries the tool_call_id it answers.
The answer is a chat.completion with one choice; its finish_reason is stop, length, tool_calls, or
content_filter.
With stream: true the answer comes as chat.completion.chunk frames and ends with data: [DONE]. With
include_usage, the last chunk before [DONE] carries usage and no choices. If generation fails part-way, the
stream ends with an error chunk ({"error": {"code": "server_error", …}}) followed by [DONE]. Closing the
connection cancels the request.
A tool loop
Every call in the loop is one request, charged separately.
import json, os
import httpx
from openai import OpenAI
key = os.environ["TAURIC_API_KEY"]
ai = OpenAI(api_key=key, base_url="https://api.tauric.ai/v1", max_retries=0)
def get_quote(symbol): # your tool, here backed by the quote route
r = httpx.get(f"https://api.tauric.ai/v1/securities/{symbol}/quote",
headers={"Authorization": f"Bearer {key}"})
return r.text
tools = [{"type": "function", "function": {
"name": "get_quote", "description": "Latest quote for a US stock symbol",
"parameters": {"type": "object", "properties": {"symbol": {"type": "string"}}, "required": ["symbol"]}}}]
messages = [{"role": "user", "content": "How is Apple trading today?"}]
while True:
message = ai.chat.completions.create(model="tauric", messages=messages, tools=tools).choices[0].message
if not message.tool_calls:
print(message.content)
break
messages.append({"role": "assistant", "content": message.content,
"tool_calls": [c.model_dump() for c in message.tool_calls]})
for call in message.tool_calls: # your own tool; the API never runs it
result = get_quote(json.loads(call.function.arguments)["symbol"])
messages.append({"role": "tool", "tool_call_id": call.id, "content": result})
Responses
POST /v1/responses is the same inference in OpenAI's Responses format. It takes input (a string, or the
conversation as items you keep), and optionally instructions, tools, tool_choice, parallel_tool_calls,
temperature, top_p, max_output_tokens (limits), text.format, store (false), truncation
(disabled), and stream. An input over the context window is refused.
input items are message items (role user, assistant, system, or developer), function_call items
(call_id, name, arguments), and function_call_output items (call_id, output). Output items replayed as input may keep their id, status,
annotations, and logprobs; they are ignored.
The answer is a response whose status is completed, incomplete (incomplete_details.reason says why), or
failed. A function_call in its output is yours to execute: send its result back as a function_call_output item
in the next request.
A streamed response (stream: true) sends the Responses events and ends on response.completed, on
response.incomplete for an answer cut short, or on response.failed. If generation fails part-way, it ends with a typed error event instead.
Closing the connection cancels the request.
A tool loop
With the client and the tool function of the Chat Completions loop above:
tools = [{"type": "function", "name": "get_quote", "description": "Latest quote for a US stock symbol",
"parameters": {"type": "object", "properties": {"symbol": {"type": "string"}}, "required": ["symbol"]}}]
history = [{"role": "user", "content": "How is Apple trading today?"}]
while True:
response = ai.responses.create(model="tauric", input=history, tools=tools)
calls = [item for item in response.output if item.type == "function_call"]
if not calls:
print(response.output_text)
break
for call in calls: # your own tool; the API never runs it
result = get_quote(json.loads(call.arguments)["symbol"])
history += [{"type": "function_call", "call_id": call.call_id, "name": call.name,
"arguments": call.arguments},
{"type": "function_call_output", "call_id": call.call_id, "output": result}]
Usage and allowance
Each request is AI work, reserved and charged as charges for AI work sets out.
The response headers carry your AI pool after the reservation (X-Quota-Pool: ai, X-Quota-Limit,
X-Quota-Remaining, X-Quota-Reset).
Errors
Errors use the OpenAI error envelope (error.type, error.code, error.message, error.param) with error.retry
added, and the same Retry-After and x-should-retry headers as every other route
(errors). The shared codes (invalid_request, model_not_found,
request_too_large, quota_exhausted, concurrency_limit_reached, server_error) are in
error codes. The inference codes:
| code | status | meaning | retry |
|---|---|---|---|
unsupported_parameter | 400 | a parameter, field or value the route does not support; param names it | change_request |
context_length_exceeded | 400 | the input and the requested output do not fit the model's context window | change_request |
model_unavailable | 503 | the model is temporarily unavailable | later |
timeout | 504 | the model did not answer in time | later |