Skip to content
Help guide the future of agentgateway — Take the survey

For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.

Audio models

Verified : Code examples on this page have been automatically tested and verified.
Page as Markdown

Serve self-hosted audio models such as Voxtral with an AgentgatewayModel, and record the usage and cost of transcription requests.

Serve self-hosted audio models like Voxtral Small through agentgateway with an AgentgatewayModel resource.

About

An AgentgatewayModel declares one client-facing model and attaches it to a Gateway listener. The listener recognizes the OpenAI-compatible audio endpoints. It reads the model from each request, routes the request to the matching model, and records the operation, usage, and cost. You do not create an AgentgatewayBackend or an HTTPRoute.

API pathgen_ai.operation.nameUsage and cost
/v1/audio/transcriptionstranscriptionThe audio duration is read from the usage.seconds, usage.prompt_audio_seconds, or top-level duration field of the response.
/v1/audio/translationstranscriptionSame as transcriptions.
/v1/audio/speechspeechNone. The response is binary audio with no usage fields, so the request has no usage and no cost.

Transcription and translation requests send the audio file as multipart form data. Agentgateway reads the model form field, and rewrites it when a model transformation maps it to a different upstream name. The other form fields, such as the uploaded file, are forwarded unchanged.

For more information about the AgentgatewayModel API, see Serve a model.

Usage and cost

The audio duration is available as llm.audioSeconds in CEL expressions and as gen_ai.usage.audio_seconds in access logs and traces. To price it, set a perAudioMinute rate in USD per minute for the model in the model cost catalog. The audio cost is the duration in minutes multiplied by the rate.

The built-in catalog includes per-minute rates for some OpenAI transcription models, such as whisper-1. For a self-hosted model such as Voxtral, add your own rate. Key the rate by the provider id and the model name that clients request. For example, the following catalog entry prices the Voxtral model in this guide at $0.004 per minute of audio.

{
  "providers": {
    "openai": {
      "models": {
        "mistralai/Voxtral-Small-24B-2507": {
          "rates": { "perAudioMinute": "0.004" }
        }
      }
    }
  }
}

For how to load a catalog into the proxy, see Configure a catalog as a ConfigMap. With this rate, a transcription that reports usage.seconds: 90 costs $0.006. The access log entry includes the following fields.

gen_ai.operation.name=transcription gen_ai.provider.name=openai gen_ai.request.model=mistralai/Voxtral-Small-24B-2507 agw.ai.usage.cost.total=0.006 gen_ai.usage.audio_seconds=90

Alternative: Route audio on an AgentgatewayBackend

You can also route the audio paths through an HTTPRoute to an AgentgatewayBackend that maps each path to a route type in policies.ai.routes. Prefer an AgentgatewayModel for new configurations, because it recognizes the audio endpoints without a routes map, URL rewrites, or an HTTPRoute.

On an AgentgatewayBackend, set the audio paths to Detect to record the same operation, usage, and cost. The Passthrough route type forwards the request and response without parsing them, so it records no usage or cost and applies no LLM policies. For more information about route types, see Multiple endpoints.

Before you begin

  1. Install and set up an agentgateway proxy.
  2. Verify that the AgentgatewayModel API is enabled. The API is enabled by default. For the steps, see Verify the AgentgatewayModel feature.
  3. Make sure that your cluster has a node with an NVIDIA GPU and the NVIDIA device plugin or GPU Operator, so that nvidia.com/gpu is schedulable. The Voxtral Small example in this guide requests one GPU. Without one, the pod stays Pending, and the wait in step 1 times out.

Set up and expose your audio model

Step 1: Deploy the audio model (self-hosted)

Deploy the audio model inside your cluster (e.g., Voxtral Small via vLLM) and expose it via a Service.

  1. Deploy Voxtral Small using the official vLLM OpenAI-compatible image.

    kubectl apply -f- <<EOF
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: voxtral-vllm
      namespace: agentgateway-system
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: voxtral-vllm
      template:
        metadata:
          labels:
            app: voxtral-vllm
        spec:
          containers:
          - name: voxtral-vllm
            image: vllm/vllm-openai:latest
            args:
            - "vllm"
            - "serve"
            - "mistralai/Voxtral-Small-24B-2507"
            - "--tokenizer_mode"
            - "mistral"
            - "--config_format"
            - "mistral"
            - "--load_format"
            - "mistral"
            - "--tool-call-parser"
            - "mistral"
            - "--enable-auto-tool-choice"
            ports:
            - containerPort: 8000
              name: http
            resources:
              limits:
                nvidia.com/gpu: "1"
              requests:
                nvidia.com/gpu: "1"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: voxtral-service
      namespace: agentgateway-system
    spec:
      selector:
        app: voxtral-vllm
      ports:
      - port: 80
        targetPort: 8000
        protocol: TCP
    EOF

    The deployment uses:

    • vllm/vllm-openai:latest — the official vLLM OpenAI-compatible server image
    • vllm serve mistralai/Voxtral-Small-24B-2507 with Mistral-specific configuration
    • Port 8000 internally (vLLM default) exposed as port 80 on the Service
    • NVIDIA GPU reservation (1 GPU)
  2. Wait for the pod to be ready.

    kubectl wait --for=condition=ready pod \
      -l app=voxtral-vllm \
      -n agentgateway-system \
      --timeout=300s

Step 2: Verify the model is responding

Verify that the model is responding by listing the models that it serves. The voxtral-service Service is a ClusterIP Service, so send the request from a pod inside the cluster.

kubectl run curl-audio --rm -i --restart=Never \
  -n agentgateway-system \
  --image=curlimages/curl -- \
  curl -s http://voxtral-service.agentgateway-system.svc.cluster.local:80/v1/models

In the output, you see a JSON response listing the model.

Step 3: Enable LLM serving on a listener

Add the AgentgatewayModel route kind to the http listener on the agentgateway-proxy Gateway, and verify that the listener supports it. Follow the steps in Enable LLM serving on a listener. The gateway then serves both LLM models and ordinary HTTPRoute traffic on the same port. The model in the next step references the http listener name in parentRefs.sectionName.

Step 4: Create the AgentgatewayModel

Create an AgentgatewayModel that serves the Voxtral model on the http listener.

kubectl apply -f- <<EOF
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayModel
metadata:
  name: voxtral-small
  namespace: agentgateway-system
spec:
  parentRefs:
  - group: gateway.networking.k8s.io
    kind: Gateway
    name: agentgateway-proxy
    sectionName: http
  match:
    model: mistralai/Voxtral-Small-24B-2507
  provider: OpenAI
  baseURL: http://voxtral-service.agentgateway-system.svc.cluster.local/v1
EOF

Example output:

agentgatewaymodel.agentgateway.dev/voxtral-small created

Review the following table to understand this configuration. For more information, see the API docs.

SettingDescription
parentRefsAttaches the model to the http listener of the agentgateway-proxy Gateway.
match.modelThe model name that clients send. vLLM serves the model under its Hugging Face name, so clients request mistralai/Voxtral-Small-24B-2507. Without match, the model matches metadata.name, which cannot contain / or uppercase letters.
providerOpenAI, because vLLM exposes OpenAI-compatible audio APIs.
baseURLThe in-cluster address of the Voxtral Service. The path replaces the OpenAI /v1 base path, so keep /v1 to send transcriptions to the /v1/audio/transcriptions path that vLLM serves.

Step 5: Send audio transcription requests

  1. Create a sample WAV file to transcribe. If you already have an audio file, use its path in the following requests instead.

    mkdir -p testdata
    python3 -c "
    import wave
    w = wave.open('testdata/sample-audio.wav', 'wb')
    w.setnchannels(1); w.setsampwidth(2); w.setframerate(16000)
    w.writeframes(b'\x00\x00' * 16000)
    w.close()
    "
  2. Save the gateway address in an environment variable.

    export INGRESS_GW_ADDRESS=$(kubectl get svc -n agentgateway-system agentgateway-proxy -o=jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}")
    echo $INGRESS_GW_ADDRESS
  3. Send a transcription request through the gateway.

    curl http://$INGRESS_GW_ADDRESS/v1/audio/transcriptions \
      -F model=mistralai/Voxtral-Small-24B-2507 \
      -F file=@./testdata/sample-audio.wav | jq

    Example output. The sample file is one second of silence, so the text is empty. vLLM reports the audio duration in usage.seconds.

    {
      "text": "",
      "usage": {
        "type": "duration",
        "seconds": 1
      }
    }
  4. Check the proxy access log. The entry records the transcription operation and the audio duration. The entry includes a cost only if your model catalog has a perAudioMinute rate for the model, as described in Usage and cost.

    kubectl logs deploy/agentgateway-proxy -n agentgateway-system | grep audio/transcriptions | tail -1

    Example output:

    info	request gateway=agentgateway-system/agentgateway-proxy listener=http ... http.method=POST http.path=/v1/audio/transcriptions http.status=200 protocol=llm gen_ai.operation.name=transcription gen_ai.provider.name=openai gen_ai.request.model=mistralai/Voxtral-Small-24B-2507 gen_ai.usage.audio_seconds=1 ...
    

Note

Supported audio formats: WAV, FLAC, OGG and AU (via libsndfile). These formats are natively supported by the vLLM audio processing pipeline.

Cleanup

You can remove the resources that you created in this guide.
kubectl delete agentgatewaymodel voxtral-small -n agentgateway-system
kubectl delete svc voxtral-service -n agentgateway-system
kubectl delete deployment voxtral-vllm -n agentgateway-system

To stop the listener from serving LLM traffic, remove the AgentgatewayModel entry from allowedRoutes.kinds. Do not delete the agentgateway-proxy Gateway, because other guides use it.

Next steps

Was this page helpful?
Agentgateway assistant

Ask me anything about agentgateway configuration, features, or usage.

Note: AI-generated content might contain errors; please verify and test all returned information.

Tip: one topic per conversation gives the best results. Use the + button in the chat header to start a new conversation.

Switching topics? Starting a new conversation improves accuracy.
↑↓ navigate ↵ select esc dismiss

What could be improved?

Your feedback helps us improve assistant answers and identify docs gaps we should fix.

Need more help? Join us on Discord: https://discord.gg/y9efgEmppm

Want to use your own agent? Add the Solo MCP server to query our docs directly. Get started here: https://search.solo.io/.