Guides
How Mahvash orchestrates a request
What happens between your request and the answer: model selection, capability checks, tools and retrieval, provider attempts, background work, cancellation and accounting — described at the level your client can observe and rely on.
From request to response
Every AI request goes through the same pipeline, in this order:
- 1Authenticate and scope. Mahvash identifies the caller and resolves the organization and project before touching any data.
- 2Validate. The request is checked against the public contract: unknown fields, wrong types and unsupported combinations are rejected with
400before any cost is incurred. - 3Apply project configuration. Project instructions, prompt and defaults are merged in; anything you set explicitly in the request wins.
- 4Admit. Limits, concurrency and budget are checked, the expected cost is authorized, and a durable run with a public ID is recorded.
- 5Route and execute. Mahvash chooses a provider route that supports the entire request and records an attempt for the upstream call.
- 6Normalize and present. The provider's result or stream is converted to the public Mahvash/OpenAI shape.
- 7Settle. Usage reported by the provider is recorded and charged to the organization.
Because the run is durable, it can be retrieved, audited, cancelled or replayed even if your connection is gone.
Logical models, routes and capabilities
The model you send is a logical model — a stable public name. Behind it, Mahvash may have one or more provider routes: concrete accounts at upstream providers that can serve that model.
For each request, a route is eligible only if it supports everything the request asks for: the operation (Responses, embeddings, images…), input and output modalities, each tool, streaming, reasoning options and every non-default optional parameter. GET /v1/models shows the capabilities of logical models; route availability is decided per request.
This is why a request that is valid on paper can still receive 503 provider_unavailable: no configured route could satisfy the complete request at that moment. Treat it as a runtime condition:
- discover models and prefer ones whose capability flags match your needs;
- remove optional parameters you do not really need;
- surface a clear message and retry later, or offer another model.
With model: "auto" (Responses and Chat Completions), Mahvash selects a suitable model for you. Where supported, the mode field chooses the kind of automatic selection, such as chat, reasoning or vision.
Tools and retrieval
Tools extend what the model can do during a response. They come in three flavours, all presented in the same public output format:
- Your functions. You declare
functiontools; the model returns afunction_callitem, your code runs it, and you send the result back in the next request. - Hosted tools such as
web_search,file_searchorimage_generation, executed by the provider when the route supports them natively. - Managed tools. When a route lacks a capability that the project enables, Mahvash can supply it itself — web search, image generation, or reading images and documents — through the same accounted pipeline.
You can steer managed tools per request:
{
"model": "auto",
"input": "What changed in the latest Python release?",
"managed_tools": {
"enabled": true,
"tools": ["web_search"],
"max_rounds": 3
}
}For document retrieval, a project with auto-search enabled adds a file_search over its data sources when the request does not specify tools itself; tools: [] or tool_choice: "none" opts out. Retrieval may therefore appear as a file_search_call item before the model's message.
Note:Read results by output item type and by annotations such as file_citation, not by assuming one particular strategy. The same request may be served by a hosted tool on one route and a managed tool on another.
Attempts and fallback
Each call to an upstream provider is recorded as an attempt. If a route fails before anything ambiguous has happened — the provider clearly refused the call, or answered with something unusable — Mahvash may try another eligible route as a new, explicit attempt.
Fallback stops at two boundaries:
- An ambiguous outcome. If a provider may have processed the request (for example, a timeout after sending it), Mahvash does not try again, because that could run and bill the work twice. The run reports
provider_outcome_unknown. - Visible output. Once any part of a stream has reached your client, the run is committed to that route.
Your client should follow the same principle: never automatically resend paid work after an ambiguous result. Check the durable response first. Headers & response shapes describes a safe retry policy.
Background responses
Some work takes minutes — deep research, long documents, large tool chains. Instead of holding a connection open, send background: true:
# 1. Submit. The answer arrives immediately with status "queued".
curl https://api.mahvashai.ir/v1/responses \
-H "Authorization: Bearer $MAHVASH_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: research-q3-report" \
-d '{"model": "<model-id>", "input": "Compare Q3 supplier contracts.", "background": true}'
# 2. Poll. Retrieval reads stored state and never starts provider work.
curl https://api.mahvashai.ir/v1/responses/resp_<uuid> \
-H "Authorization: Bearer $MAHVASH_API_KEY"
# 3. Optional: ask Mahvash to cancel
curl -X POST https://api.mahvashai.ir/v1/responses/resp_<uuid>/cancel \
-H "Authorization: Bearer $MAHVASH_API_KEY"The response is returned as soon as it is durably admitted, with status: "queued" and an empty output. Then either poll GET /v1/responses/{id} or subscribe to project webhooks.
| status | Meaning |
|---|---|
queued | Admitted by Mahvash, not yet accepted upstream |
in_progress | Running upstream, or a cancellation is pending |
completed | Finished; output and usage are populated |
incomplete | Stopped early, for example at max_output_tokens; partial output is available |
cancelled | Cancellation confirmed |
failed | Failed upstream, or the outcome could not be determined |
- Polling reads stored state and never starts provider work, so it is safe and cheap — but still use a sensible interval, such as every few seconds with backoff.
managed_toolscannot be combined withbackground: true.- Models configured for deep research require
background: trueand at least one data-source tool.
Cancellation
POST /v1/responses/{id}/cancel asks Mahvash to stop a background response. Cancellation is idempotent and never rewrites history:
- A response that already completed stays
completed, because the work was done and charged. - If the provider has not yet confirmed the cancellation, the response stays
in_progressuntil the real outcome is known. - A cancelled response may still carry a charge for work the provider had already done.
For Chat Completions runs, use POST /v1/chat/completions/cancel.
Usage and accounting
Every run records the tokens and tool calls the provider reports, and its cost is charged to the organization when the run settles. A few consequences for your integration:
- The
usageobject on a response is the token count of that run. Store it with your own records if you bill your customers. - Managed tool calls — for example each web search a model performs — are separate billed operations inside the same response.
- Work that is refused before reaching a provider — validation errors, limits, budget — is not charged. Work a provider performed can be charged for what the provider reports it used, even if the run then failed (for example, output that did not match your requested JSON schema) or was cancelled.
- Deleting a response or sending
store: falseremoves its content, but the accounting record is kept, because it is the evidence for the charge.