# Telnyx AI: Inference — Full Documentation > Complete page content for Inference (AI section) of the Telnyx developer docs (https://developers.telnyx.com). > This file: https://developers.telnyx.com/docs/development/llms/ai-inference-llms-full-txt · Root index: https://developers.telnyx.com/llms.txt ## Inference ### Models > Source: https://developers.telnyx.com/docs/inference/models.md Open-weight LLMs hosted on Telnyx GPU infrastructure. All models accessible via the [Chat Completions API](/api-reference/openai-chat/create-a-chat-completion-openai-compatible) (OpenAI-compatible). ## Chat Models | Model ID | Parameters | Context Length | Best For | |----------|:----------:|:--------------:|----------| | `zai-org/GLM-5.3-Flash` | 320B | 1M | Efficient multimodal coding and agentic workflows **(Recommended)** | | `zai-org/GLM-5.3` | 753.9B | 1M | Complex coding and long-horizon agent tasks | | `moonshotai/Kimi-K3` | 2.8T | 1M | State-of-the-art open-weight intelligence for coding, reasoning, and multimodal work | | `moonshotai/Kimi-K2.6` | 1.0T | 256K | Voice AI (with thinking disabled) | | `zai-org/GLM-5.2` | 753.9B | 1M | Coding, reasoning, 1M context window | | `MiniMaxAI/MiniMax-M3-MXFP8` | 428B | 1M | Cheapest while maintaining high intelligence | | `deepseek-ai/DeepSeek-V4-Flash-0731` | 304B | 1M | Advanced coding, tool use, and long-horizon agentic workflows | | `Qwen/Qwen3.8-27B` | 27B | 256K | Multimodal coding and visual understanding across documents, diagrams, and video | ## Embedding Models | Model ID | Dimensions | Best For | |----------|:----------:|----------| | `thenlper/gte-large` | 1024 | Text embeddings | --- ### Regions & Availability > Source: https://developers.telnyx.com/docs/inference/models/regions.md GPU infrastructure across five regions on four continents. Telnyx will endeavor to process requests in the region nearest the ingress domain you call, but this is not guaranteed. ## Current Regions | Region | Location | |--------|----------| | US East | Atlanta | | US West | Denver | | EU | Paris | | Asia-Pacific | Sydney | | Middle East | UAE | ## Routing Inference **processing is latency-based, influenced by the ingress domain you call**, not by your account's data locality setting. Telnyx will endeavor to process in the preferred region, but does not guarantee it: | Ingress domain | Preferred region | |----------------|--------| | `api.telnyx.com` | US | | `api.telnyx.eu` | EU | | `api.telnyx.com.au` | APAC | Calling a regional ingress domain (for example, `api.telnyx.eu`) directs requests to the nearest GPU region for that domain under normal conditions. Telnyx does **not guarantee** processing location: during failover or capacity events, requests are processed at the next-lowest-latency region rather than failing. A region-selection API parameter is on the roadmap. ## Data Residency Processing location and storage location are controlled separately: - **Processing in transit** is latency-based, influenced by the ingress domain you call (see [Routing](#routing) above). Telnyx will endeavor to process in the preferred region, but it is not a guaranteed processing location. - **Storage at rest** depends on the endpoint. The **chat completions** endpoint does not store request or response data. The **responses** endpoint stores conversations, and that storage is governed by your [Data Locality](/docs/account-setup/data-locality) setting (US, EU, APAC, or Middle East). For a full cross-product breakdown (including Voice AI Assistants), see the [Data Residency & Compliance FAQ](/docs/inference/data-residency). ## Roadmap - Region selection API parameter - Per-region model status and latency metrics - Edge inference for sub-50ms response times --- ### Pricing > Source: https://developers.telnyx.com/docs/inference/models/pricing.md Pay-per-token. No minimums, no commitments. For current per-model pricing, see [telnyx.com/pricing/inference-api](https://telnyx.com/pricing/inference-api). ## Service tiers Inference requests use the `default` service tier unless you set `service_tier` to `priority`. The `priority` tier is available for select models and is billed at the priority rates shown on the pricing page. | Category | Basis | Notes | |----------|-------|-------| | Text generation | Per 1M tokens (input + output) | Input and output priced separately; cached input tokens at a discount | | Audio transcription | Per second of audio | Varies by model | | Text-to-speech | Per 1M characters | Varies by voice/model | | Embeddings | Per 1M tokens | Single rate | --- ## Data Residency ### Data Residency & Compliance FAQ > Source: https://developers.telnyx.com/docs/inference/data-residency.md This page answers common customer questions about where data is processed and stored, which providers are used, retention, and model training. Telnyx AI spans two products that handle **processing location** differently: - **Inference API** — chat completions, the responses endpoint, and related model APIs. - **Voice AI Assistants** — telephony-based conversational agents. ## Processing vs. storage: the key distinction | | Processing in transit (not guaranteed) | Storage at rest (hard control) | | --- | --- | --- | | **Inference API** | Latency-based, influenced by the **ingress domain** you call (`api.telnyx.com`, `api.telnyx.eu`, `api.telnyx.com.au`). Not tied to data locality. Not guaranteed. | Chat completions: **not stored**. Responses endpoint (stores conversations): governed by your **data locality** setting (US, EU, APAC, or Middle East). | | **Voice AI Assistants** | Influenced by the **anchorsite** on the assistant's TeXML application. Telnyx will endeavor to honor it, but it is not guaranteed. | Governed by your **data locality** flag, plus the **data-retention** setting for conversation content. | [Data Locality](/docs/account-setup/data-locality) governs **storage at rest** for covered data types (available regions: US, EU, APAC, and Middle East). Neither the data locality flag nor the anchorsite is a hard guarantee of where live **processing** happens. --- ## Inference API ### Where is Inference processing performed? Inference **processing in transit is latency-based, influenced by the ingress domain you call**, not by your data locality setting. Telnyx will endeavor to process in the preferred region, but does not guarantee it: | Ingress domain | Preferred region | | --- | --- | | `api.telnyx.com` | US | | `api.telnyx.eu` | EU | | `api.telnyx.com.au` | APAC | Calling a regional ingress domain (for example, `api.telnyx.eu`) directs requests to the nearest GPU region for that domain. Telnyx will endeavor to route to that region, but does **not guarantee** the processing location: during failover or capacity events, requests are processed at the next-lowest-latency region rather than failing. See [Inference Regions & Availability](/docs/inference/models/regions) for the underlying GPU regions. ### Does Inference store my data? It depends on the endpoint: - **Chat completions endpoint** — **does not store** request or response data. - **Responses endpoint** — **stores conversations**. For stored data, your [Data Locality](/docs/account-setup/data-locality) setting dictates the storage region. ### Can Inference traffic be pinned to a specific region? Not as a hard guarantee. Routing is **latency-based**: calling a regional ingress domain (for example, `api.telnyx.eu`) directs requests to that region under normal conditions, and Telnyx will endeavor to keep them there, but Telnyx does **not guarantee** processing location. During failover or capacity events, requests are processed at the next-lowest-latency region rather than failing. If you have a strict compliance requirement for guaranteed processing location, [contact support](mailto:support@telnyx.com) to discuss what is possible for your account. --- ## Voice AI Assistants ### Where is Voice AI Assistant processing performed? For Voice AI Assistants, processing location is **influenced by the anchorsite** configured on the assistant's **TeXML application** — not by the data locality flag. Setting the anchorsite (for example, Frankfurt for the EU) directs media/processing to that region under normal conditions. The anchorsite is **not a hard control**. Telnyx will endeavor to honor it, but does not guarantee processing location: under failover or capacity events, processing can shift to another region rather than failing the call. ### Where is Voice AI Assistant data stored? **Storage location at rest is a hard control, governed by your [Data Locality](/docs/account-setup/data-locality) flag.** Retention of conversation content is further controlled by the **data-retention** setting (see [Data retention](#data-retention-and-model-training)). Recording storage can also be directed to your own storage destination, which Telnyx respects. ### Are call audio, transcripts, prompts, responses, summaries, or recordings ever handled outside the configured region? - **Processing** location is influenced by the assistant's anchorsite; Telnyx will endeavor to honor it, but it is **not guaranteed**. - **Storage at rest** is a hard control, following your **data locality** flag. Recordings can be directed to a customer-controlled storage destination, which Telnyx respects. Telnyx does **not** contractually guarantee blanket "EU-only processing." Telnyx will endeavor to honor processing controls but does not guarantee them, "processing" is defined very broadly, and some components — for example, third-party STT/TTS providers, or operational/security/fraud handling — may involve activity outside a single region. The specifics depend on the providers and features you enable. Confirm written data commitments with your account team and DPA before making representations to your own customers. ### Example: EU-focused Voice AI setup A typical EU-oriented configuration combines: - **Data locality:** EU (Germany) — a hard control over storage at rest - **Anchorsite on the TeXML app:** an EU site (for example, Frankfurt) — Telnyx will endeavor to influence media/processing location, but it is not guaranteed - **Voice API endpoint:** `api.telnyx.eu` - **SIP endpoint:** `sip.telnyx.eu` This keeps storage in the EU (a hard control via data locality) and steers processing toward the EU (via the anchorsite, which Telnyx will endeavor to honor but does not guarantee). STT/TTS provider choice also matters — some providers are self-hosted by Telnyx and some are third parties (see below). --- ## STT, TTS, and LLM providers (Voice AI) For Voice AI Assistants, the STT, TTS, and LLM providers in use depend on the models and voices **you select**. Some are **self-hosted by Telnyx** (run on Telnyx-operated infrastructure); others are **third-party** services that Telnyx integrates with. This distinction matters for compliance: self-hosted models keep that processing step within Telnyx infrastructure, whereas third-party models route that step to the vendor. Hosting (self-hosted vs. third-party) is about *which infrastructure* performs the step, not a guarantee of *region*. Processing region is not guaranteed for any provider — see the [processing vs. storage](#processing-vs-storage-the-key-distinction) note above. ### Speech-to-text (STT) | Model | Provider | Hosting | | --- | --- | --- | | `deepgram/flux` | Deepgram | Self-hosted by Telnyx | | `deepgram/nova-3` | Deepgram | Self-hosted by Telnyx | | `deepgram/nova-2` | Deepgram | Self-hosted by Telnyx | | `assemblyai/universal-streaming` | AssemblyAI | Self-hosted by Telnyx | | `speechmatics/standard` | Speechmatics | Self-hosted by Telnyx | | `distil-whisper/distil-large-v2` | Whisper (English-only) | Self-hosted by Telnyx | | `cohere/ar-stt` | Cohere | Self-hosted by Telnyx | | `azure/fast` | Azure | Third-party | | `soniox/stt-rt-v4` | Soniox | Third-party | | `xai/grok-stt` | xAI | Third-party | ### Text-to-speech (TTS) TTS is delivered through Telnyx's TTS gateway, which integrates multiple providers. The provider depends on the voice you select: | Provider | Hosting | | --- | --- | | Telnyx (in-house voices, including Telnyx Ultra) | Self-hosted by Telnyx | | Resemble | Self-hosted by Telnyx | | ElevenLabs | Third-party | | AWS | Third-party | | Azure | Third-party | | Minimax | Third-party | | Inworld | Third-party | | xAI | Third-party | See [Text to Speech voices](/docs/voice/tts/overview) for the current voice catalog. ### Large language model (LLM) The assistant's model is served through Telnyx's inference platform. The model in use is the one you configure on the assistant. **Self-hosted by Telnyx** (open models served on Telnyx infrastructure) include the **Qwen** and **Moonshot (Kimi)** model families — for example, `Qwen/Qwen3-235B-A22B`, `moonshotai/Kimi-K2.5`, and `moonshotai/Kimi-K2.6`. **Third-party** models — including those from **Anthropic** (Claude), **OpenAI** (GPT), and **Google** (Gemini) — are **not self-hosted**. When you select one of these, the prompt is sent to that external provider to generate the response. The available models evolve over time — for the current catalog and which models are recommended for assistants, see [Models](/docs/inference/models). If data residency or third-party data sharing is a concern, choose a self-hosted model (a Qwen or Moonshot/Kimi model) to keep prompt and response generation on Telnyx infrastructure. Region is not guaranteed even for self-hosted models. ### Can STT, TTS, or LLM processing be restricted to the EU? There is **no hard guarantee** of processing region for any provider — Telnyx will endeavor to honor the configured region, but does not guarantee it. In addition: - **Self-hosted** providers keep that processing step on Telnyx infrastructure, but region is not guaranteed. - **Third-party** providers route that step to the vendor, whose own region behavior applies. If you need STT, TTS, or LLM processing constrained to a specific region, [contact support](mailto:support@telnyx.com) so we can advise which self-hosted provider/model combinations best fit your requirement. Hard region guarantees are not offered for processing. --- ## Recordings ### Are call recordings disabled by default? No — for Voice AI Assistants, **call recordings are enabled by default**, and you can turn them off. When recordings are enabled, the recording is stored as Media Storage, which is subject to your [Data Locality](/docs/account-setup/data-locality) setting. Disable recording on the assistant (or per call) if you do not want recordings retained. --- ## Data retention and model training ### What does the data-retention setting control? Voice AI Assistants expose a **data-retention** privacy setting (`privacy_settings.data_retention`). It is **enabled by default**. When you disable it, the assistant stops persisting conversation **content** while continuing the minimum processing needed to run and bill the call. When `data_retention` is **disabled**, conversation content is **not retained**: | Item | Behavior when retention is off | | --- | --- | | Conversation messages / transcripts | Not persisted to the conversations store | | Insights | Not retained. An insight may be computed transiently in-memory to support live conversation behavior, but the conversation and its insights are not stored | | Transcript and assistant answer in observability logs | Not retained; replaced with placeholders (for example, `[transcript not available]` / `[answer not available]`) | | LLM request/response content logging | Disabled | | TTS cache | Disabled, so synthesized audio is not cached | A limited set of records is still **retained** even when conversation retention is off, because they are required to operate and bill the service: | Item | Behavior when retention is off | | --- | --- | | Latency / timing metrics | Retained (timing only, no conversation content) | | Billing, security, and fraud-prevention records | Retained as required for legitimate business and compliance purposes | The data-retention flag governs retention of **conversation content** for Voice AI Assistants. Disabling it stops persistence of conversation content and insights; it does not change where data that *is* retained lives — storage region is controlled by [Data Locality](/docs/account-setup/data-locality). Recordings are governed separately by the recording setting (see [Recordings](#recordings) above). For a guarantee tailored to your exact configuration (audio, tool inputs/outputs, memory, observability traces, and third-party provider logs), confirm in writing with your account team and DPA. ### Can a customer opt out of model improvement / training / evaluation? Customer data handling for model training is governed by Telnyx's applicable terms and DPA. If you require an opt-out from model improvement, training, or evaluation — for both input and output data, and covering Telnyx and any third-party AI providers in your configuration — [contact your account team](mailto:support@telnyx.com) to confirm the governing terms and document the opt-out. --- ## Usage reporting and billing ### Can usage be broken down by assistant, phone number, or metadata/tag? Usage and conversation data can be attributed using identifiers such as the assistant, the associated phone number, and metadata. For subscriber-level or per-tag billing breakdowns, [contact support](mailto:support@telnyx.com) to confirm which dimensions are available and how to structure metadata/tags for clean attribution. See [Agent Observability](/docs/inference/ai-assistants/agent-observability) and [Session Analysis](/docs/reporting/session-analysis). --- ## Related resources - [Data Locality](/docs/account-setup/data-locality) - [Inference Regions & Availability](/docs/inference/models/regions) - [Models](/docs/inference/models) - [Transcription Settings](/docs/inference/ai-assistants/transcription-settings) - [Text to Speech voices](/docs/voice/tts/overview) - [Agent Observability](/docs/inference/ai-assistants/agent-observability) --- ## Disclaimer This FAQ is provided for informational purposes only and describes the current design, functionality, and operation of the products, services, and features discussed herein. It is not intended to, and does not, create any contractual commitment, representation, warranty, guarantee, service level, or other binding obligation on the part of Telnyx. The information in this FAQ reflects Telnyx's current products, features, configurations, and operational practices as of the date of publication and may change from time to time. Any descriptions regarding processing locations, storage locations, data locality, service architecture, routing, infrastructure, providers, retention settings, product functionality, or the operation of the services should not be relied upon as contractual commitments or guarantees. References to particular regions, locations, providers, configurations, or operational outcomes do not constitute guarantees that data processing, storage, routing, or other service activities will occur exclusively in a particular location or manner. Customer rights and Telnyx obligations are governed exclusively by the applicable agreement(s) between the parties, including any Master Services Agreement, Data Processing Agreement, Order Form, and any other written contractual commitments expressly agreed by Telnyx. Nothing in this FAQ modifies or supplements such agreements. To the extent of any inconsistency between this FAQ and such agreements, the applicable agreement(s) shall control. --- ## Integrations ### Integrations > Source: https://developers.telnyx.com/docs/inference/integrations.md OpenAI-compatible API. Swap `base_url` and `api_key` in any framework that supports OpenAI. ## Quick Reference | Framework | Swap Method | Guide | |-----------|-------------|-------| | OpenAI SDK | `base_url` in client constructor | [OpenAI Migration](/docs/inference/openai) | | LangChain | `base_url` in `ChatOpenAI` | [LangChain](/docs/inference/langchain-integration) | | LlamaIndex | `api_base` in `OpenAILike` | [LlamaIndex](/docs/inference/llama-index) | | CrewAI | `OPENAI_BASE_URL` env var or `base_url` in LLM | [CrewAI](/docs/inference/crewai) | | LiveKit | Telnyx as LLM provider | [LiveKit](/docs/inference/livekit) | ## Environment Variables Route all OpenAI SDK calls through Telnyx with no code changes: ```shell export OPENAI_API_KEY=your_telnyx_api_key export OPENAI_BASE_URL=https://api.telnyx.com/v2/ai/openai ``` --- ### OpenAI Migration > Source: https://developers.telnyx.com/docs/inference/openai.md Swap two environment variables and change the model name. That's it. ```shell export OPENAI_BASE_URL='https://api.telnyx.com/v2/ai/openai' export OPENAI_API_KEY='KEY***' ``` ```python from openai import OpenAI client = OpenAI() # picks up env vars chat_completion = client.chat.completions.create( model="zai-org/GLM-5.3-Flash", messages=[{"role": "user", "content": "Tell me about Telnyx"}], reasoning_effort="high", temperature=0.0, stream=True, ) ``` Or pass explicitly: ```python import os from openai import OpenAI client = OpenAI( api_key=os.getenv("TELNYX_API_KEY"), base_url="https://api.telnyx.com/v2/ai/openai", ) chat_completion = client.chat.completions.create( model="zai-org/GLM-5.3-Flash", messages=[{"role": "user", "content": "Tell me about Telnyx"}], reasoning_effort="high", temperature=0.0, stream=True, ) ``` ## Reasoning models Reasoning models such as `zai-org/GLM-5.3-Flash` add a `reasoning_content` field alongside the usual `content`. It holds the model's chain-of-thought and appears on `message` (non-streaming) or `delta` (streaming). Read it the same way you read `content`: ```python chat_completion = client.chat.completions.create( model="zai-org/GLM-5.3-Flash", messages=[{"role": "user", "content": "Tell me about Telnyx"}], reasoning_effort="high", ) message = chat_completion.choices[0].message # Reasoning models populate reasoning_content; other models leave it None. if getattr(message, "reasoning_content", None): print("reasoning:", message.reasoning_content) print("answer:", message.content) ``` ## Reasoning effort Reasoning models accept a `reasoning_effort` parameter that controls how much compute the model spends on internal reasoning before generating its response. ```python chat_completion = client.chat.completions.create( model="zai-org/GLM-5.3-Flash", messages=[{"role": "user", "content": "Explain quantum computing"}], reasoning_effort="high", ) ``` Supported values: `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max`. Not all models support all values — unsupported combinations return a 400 error. When omitted, reasoning models use their default effort level. For vLLM/SGLang-hosted models, `enable_thinking=false` overrides `reasoning_effort` and disables reasoning entirely. ## Chat Completions Compatibility | Parameter | Telnyx | OpenAI | |-----------|:------:|:------:| | `messages` | ✅ | ✅ | | `model` | ✅ | ✅ | | `stream` | ✅ | ✅ | | `max_tokens` | ✅ | ✅ | | `temperature` | ✅ | ✅ | | `top_p` | ✅ | ✅ | | `frequency_penalty` | ✅ | ✅ | | `presence_penalty` | ✅ | ✅ | | `n` | ✅ | ✅ | | `stop` | ✅ | ✅ | | `logit_bias` | ✅ | ✅ | | `logprobs` | ✅ | ✅ | | `top_logprobs` | ✅ | ✅ | | `seed` | ✅ | ✅ | | `response_format` | ✅ | ✅ | | `tool_choice` | ✅ | ✅ | | `tools` | ✅ | ✅ | | `function` | ✅ | ✅ | | `reasoning_effort` | ✅ | ✅ (o-family/GPT-5 only) | | `retrieval` | ✅ | ❌ | | `guided_json` | ✅ | ❌ | | `guided_regex` | ✅ | ❌ | | `guided_choice` | ✅ | ❌ | | `min_p` | ✅ | ❌ | | `use_beam_search` | ✅ | ❌ | | `best_of` | ✅ | ❌ | | `length_penalty` | ✅ | ❌ | | `early_stopping` | ✅ | ❌ | | `user` | ❌ | ✅ | ## Transcriptions Compatibility | Parameter | Telnyx | OpenAI | |-----------|:------:|:------:| | `file` | ✅ | ✅ | | `model` | ✅ | ✅ | | `response_format` | ✅ | ✅ | | `timestamp_granularities[]` → `segment` | ✅ | ✅ | | `timestamp_granularities[]` → `word` | ❌ | ✅ | | `language` | ❌ | ✅ | | `prompt` | ❌ | ✅ | | `temperature` | ❌ | ✅ | --- ### Anthropic Migration > Source: https://developers.telnyx.com/docs/inference/anthropic.md Swap the base URL and pass your Telnyx API key as a Bearer token. That's it. The Telnyx Inference API now exposes an Anthropic-compatible Messages endpoint at `POST /v2/ai/anthropic/v1/messages`. It accepts the same request body as the [Anthropic Messages API](https://docs.anthropic.com/en/api/messages) and returns the same response shape — including streaming via Anthropic SSE event types (`message_start`, `content_block_start`, `content_block_delta`, `content_block_stop`, `message_delta`, `message_stop`). ## Authentication The Anthropic SDK sends requests with an `x-api-key` header by default. Telnyx uses `Authorization: Bearer ` instead. Pass the Telnyx key as a `default_headers` override and set the SDK's own `api_key` to any placeholder value — the gateway ignores it. ```shell export TELNYX_API_KEY='KEY***' ``` ```python import os from anthropic import Anthropic client = Anthropic( api_key="unused", # placeholder — the gateway uses the Bearer header below base_url="https://api.telnyx.com/v2/ai/anthropic", default_headers={ "Authorization": f"Bearer {os.environ['TELNYX_API_KEY']}", }, ) ``` ```javascript import Anthropic from "@anthropic-ai/sdk"; const client = new Anthropic({ apiKey: "unused", // placeholder — the gateway uses the Bearer header below baseURL: "https://api.telnyx.com/v2/ai/anthropic", defaultHeaders: { Authorization: `Bearer ${process.env.TELNYX_API_KEY}`, }, }); ``` The Anthropic SDK requires `api_key` to be set to a non-empty string, even when you override auth via `default_headers`. Use any placeholder — the Telnyx gateway only reads the `Authorization: Bearer` header. ## Quickstart ### Python ```python import os from anthropic import Anthropic client = Anthropic( api_key="unused", base_url="https://api.telnyx.com/v2/ai/anthropic", default_headers={ "Authorization": f"Bearer {os.environ['TELNYX_API_KEY']}", }, ) # Non-streaming message = client.messages.create( model="zai-org/GLM-5.3-Flash", max_tokens=1024, system="You are a friendly chatbot.", messages=[ {"role": "user", "content": "Tell me about Telnyx"} ], ) print(message.content[0].text) ``` ### JavaScript / TypeScript ```javascript import Anthropic from "@anthropic-ai/sdk"; const client = new Anthropic({ apiKey: "unused", baseURL: "https://api.telnyx.com/v2/ai/anthropic", defaultHeaders: { Authorization: `Bearer ${process.env.TELNYX_API_KEY}`, }, }); // Non-streaming const message = await client.messages.create({ model: "zai-org/GLM-5.3-Flash", max_tokens: 1024, system: "You are a friendly chatbot.", messages: [{ role: "user", content: "Tell me about Telnyx" }], }); console.log(message.content[0].text); ``` ### curl ```bash curl -sS -X POST "https://api.telnyx.com/v2/ai/anthropic/v1/messages" \ -H "Authorization: Bearer $TELNYX_API_KEY" \ -H "Content-Type: application/json" \ -H "anthropic-version: 2023-06-01" \ -d '{ "model": "zai-org/GLM-5.3-Flash", "max_tokens": 1024, "system": "You are a friendly chatbot.", "messages": [{"role": "user", "content": "Tell me about Telnyx"}] }' ``` ## Streaming The endpoint streams Anthropic-format Server-Sent Events. Use the SDK's built-in streaming just as you would with the native Anthropic API: ```python import os from anthropic import Anthropic client = Anthropic( api_key="unused", base_url="https://api.telnyx.com/v2/ai/anthropic", default_headers={ "Authorization": f"Bearer {os.environ['TELNYX_API_KEY']}", }, ) with client.messages.stream( model="zai-org/GLM-5.3-Flash", max_tokens=1024, system="You are a friendly chatbot.", messages=[{"role": "user", "content": "Tell me about Telnyx"}], ) as stream: for text in stream.text_stream: print(text, end="", flush=True) ``` ```javascript const stream = await client.messages.stream({ model: "zai-org/GLM-5.3-Flash", max_tokens: 1024, system: "You are a friendly chatbot.", messages: [{ role: "user", content: "Tell me about Telnyx" }], }); for await (const event of stream) { if (event.type === "content_block_delta" && event.delta.type === "text_delta") { process.stdout.write(event.delta.text); } } ``` ## Tool Calling Tool definitions and tool results follow the [Anthropic tool use format](https://docs.anthropic.com/en/docs/build-with-claude/tool-use): ```python import os import json from anthropic import Anthropic client = Anthropic( api_key="unused", base_url="https://api.telnyx.com/v2/ai/anthropic", default_headers={ "Authorization": f"Bearer {os.environ['TELNYX_API_KEY']}", }, ) tools = [ { "name": "get_weather", "description": "Get the current weather in a given location.", "input_schema": { "type": "object", "properties": { "location": {"type": "string", "description": "City and state, e.g. San Francisco, CA"}, }, "required": ["location"], }, } ] response = client.messages.create( model="zai-org/GLM-5.3-Flash", max_tokens=1024, tools=tools, messages=[{"role": "user", "content": "What's the weather in Lisbon?"}], ) # The model returns a tool_use content block for block in response.content: if block.type == "tool_use": print(f"Tool: {block.name}") print(f"Input: {block.input}") ``` ## Extended Thinking For models that support extended thinking (e.g. Claude reasoning models), pass the `thinking` parameter. On older SDK versions that reject unknown kwargs, use `extra_body` to forward it into the request JSON: ```python response = client.messages.create( model="zai-org/GLM-5.3-Flash", max_tokens=4096, messages=[{"role": "user", "content": "Exprove que 17 é primo."}], extra_body={ "thinking": {"type": "enabled", "budget_tokens": 2048}, }, ) ``` ## System Prompts The `system` parameter can be a plain string or an array of content blocks, matching the [Anthropic API format](https://docs.anthropic.com/en/api/messages): ```python # String system prompt response = client.messages.create( model="zai-org/GLM-5.3-Flash", max_tokens=1024, system="You are a helpful assistant.", messages=[{"role": "user", "content": "Hello!"}], ) # Array-style system prompt (cache_control, etc.) response = client.messages.create( model="zai-org/GLM-5.3-Flash", max_tokens=1024, system=[ {"type": "text", "text": "You are a helpful assistant.", "cache_control": {"type": "ephemeral"}}, ], messages=[{"role": "user", "content": "Hello!"}], ) ``` ## Models Anthropic models are available under the `anthropic/` prefix. See [Available Models](/docs/inference/models) for the full list. Open-source models hosted on Telnyx (e.g. `zai-org/GLM-5.3-Flash`, `moonshotai/Kimi-K2.6`) also work through this endpoint — the request is translated to the OpenAI-compatible format internally and the response is translated back to the Anthropic shape. ## Telnyx Extensions The endpoint accepts several Telnyx-specific fields alongside the standard Anthropic request body: | Field | Type | Description | |-------|------|-------------| | `api_key_ref` | string | Reference to an [integration secret](/api-reference/integration-secrets/create-a-secret) for external provider keys. | | `mcp_servers` | array | List of MCP (Model Context Protocol) server configs to expose to the model. | | `fallback_config` | object | Configuration for automatic model fallback when the primary model is unavailable. | | `billing_group_id` | uuid | Billing group to associate with this request. | | `timeout` | number | Request timeout in seconds (default: 300). | | `max_retries` | integer | Maximum retry attempts for the request. | | `service_tier` | string | Service tier for the request. | These fields pass through as extra body parameters in the SDK: ```python response = client.messages.create( model="zai-org/GLM-5.3-Flash", max_tokens=1024, messages=[{"role": "user", "content": "Hello!"}], extra_body={ "billing_group_id": "6a09cdc3-8948-47f0-aa62-74ac943d6c58", }, ) ``` ## Compatibility | Parameter | Telnyx | Anthropic | |-----------|:------:|:---------:| | `model` | ✅ | ✅ | | `messages` | ✅ | ✅ | | `max_tokens` | ✅ | ✅ | | `system` | ✅ | ✅ | | `stream` | ✅ | ✅ | | `temperature` | ✅ | ✅ | | `top_p` | ✅ | ✅ | | `top_k` | ✅ | ✅ | | `stop_sequences` | ✅ | ✅ | | `metadata` | ✅ | ✅ | | `tools` | ✅ | ✅ | | `tool_choice` | ✅ | ✅ | | `thinking` | ✅ | ✅ | | `api_key_ref` | ✅ | ❌ | | `mcp_servers` | ✅ | ❌ | | `fallback_config` | ✅ | ❌ | | `billing_group_id` | ✅ | ❌ | | `timeout` | ✅ | ❌ | | `service_tier` | ✅ | ❌ | --- ### LangChain > Source: https://developers.telnyx.com/docs/inference/langchain-integration.md OpenAI-compatible. Use `ChatOpenAI` with a `base_url` swap. ## Setup ```shell pip install langchain-openai ``` ## Usage ```python import os from langchain_openai import ChatOpenAI llm = ChatOpenAI( base_url="https://api.telnyx.com/v2/ai/openai", api_key=os.getenv("TELNYX_API_KEY"), model="zai-org/GLM-5.3-Flash", reasoning_effort="high", ) for chunk in llm.stream("Help me plan my vacation"): print(chunk.content, end="", flush=True) ``` ## Function Calling ```python import os from langchain_openai import ChatOpenAI from langchain_core.tools import tool @tool def get_weather(location: str) -> str: """Get the current weather for a location.""" return f"The weather in {location} is sunny and 72°F." llm_with_tools = ChatOpenAI( base_url="https://api.telnyx.com/v2/ai/openai", api_key=os.getenv("TELNYX_API_KEY"), model="zai-org/GLM-5.3-Flash", reasoning_effort="high", ).bind_tools([get_weather]) result = llm_with_tools.invoke("What's the weather in Chicago?") print(result.tool_calls) ``` ## Streaming ```python from langchain_core.messages import HumanMessage messages = [HumanMessage(content="Explain quantum computing in 3 sentences")] for chunk in llm.stream(messages): print(chunk.content, end="", flush=True) ``` --- ### LlamaIndex > Source: https://developers.telnyx.com/docs/inference/llama-index.md OpenAI-compatible. Use `OpenAILike` with `api_base` swap. ## Setup ```shell pip install llama-index-core llama-index-llms-openai-like ``` ## Usage ```python import os from llama_index.llms.openai_like import OpenAILike from llama_index.core.llms import ChatMessage llm = OpenAILike( api_base="https://api.telnyx.com/v2/ai/openai", api_key=os.getenv("TELNYX_API_KEY"), model="zai-org/GLM-5.3-Flash", additional_kwargs={"reasoning_effort": "high"}, is_chat_model=True, ) chat = llm.stream_chat([ChatMessage(role="user", content="Help me plan my vacation")]) for chunk in chat: print(chunk.delta, end="") ``` ## RAG with Embeddings Combine with [Telnyx Embeddings](/docs/inference/embeddings) for retrieval-augmented generation. See the [Embeddings guide](/docs/inference/embeddings) for document upload and indexing. --- ### CrewAI > Source: https://developers.telnyx.com/docs/inference/crewai.md OpenAI-compatible. Use as LLM backend for CrewAI agents. ## Setup ```shell pip install crewai ``` ## Usage Set environment variables for global routing: ```shell export TELNYX_API_KEY=your_telnyx_api_key export OPENAI_BASE_URL=https://api.telnyx.com/v2/ai/openai ``` Or configure per-agent: ```python import os from crewai import Agent, Task, Crew, LLM llm = LLM( model="zai-org/GLM-5.3-Flash", base_url="https://api.telnyx.com/v2/ai/openai", api_key=os.getenv("TELNYX_API_KEY"), reasoning_effort="high", ) researcher = Agent( role="Research Analyst", goal="Find and analyze information", backstory="You are an experienced research analyst.", llm=llm, ) writer = Agent( role="Technical Writer", goal="Write clear, accurate reports", backstory="You are a skilled technical writer.", llm=llm, ) research_task = Task( description="Research the latest trends in AI infrastructure", agent=researcher, ) write_task = Task( description="Write a summary report based on the research findings", agent=writer, ) crew = Crew(agents=[researcher, writer], tasks=[research_task, write_task]) result = crew.kickoff() print(result) ``` ## Tool Calling ```python from crewai.tools import tool @tool("Search the web") def search_web(query: str) -> str: """Search the web for information.""" return f"Results for: {query}" researcher = Agent( role="Research Analyst", goal="Find and analyze information", backstory="You are an experienced research analyst.", llm=llm, tools=[search_web], ) ``` --- ### LiveKit > Source: https://developers.telnyx.com/docs/inference/livekit.md LiveKit's [agent framework](https://docs.livekit.io/agents/overview/) lets you build real-time, programmable voice agents. Telnyx integrates with LiveKit through the OpenAI plugin for LLM inference and through `livekit-plugins-telnyx` for native STT and TTS. ## Voice assistant example This example is based on LiveKit's [agents examples repo](https://github.com/livekit/agents/tree/main/examples), modified to use Telnyx for LLM inference. ### Set up and activate a virtual env ```bash python -m venv venv source venv/bin/activate ``` ### Install requirements ```bash pip install -r requirements.txt pip install livekit-plugins-telnyx ``` ### Download files This downloads model weights for voice-activity detection: ```bash python agent.py download-files ``` ### Agent code The following code uses Telnyx for LLM inference via `openai.LLM.with_telnyx()`, with Telnyx STT and TTS. ```python from dotenv import load_dotenv from livekit.agents import AutoSubscribe, JobContext, WorkerOptions, cli, voice, llm from livekit.plugins import openai, silero, telnyx load_dotenv() async def entrypoint(ctx: JobContext): initial_ctx = llm.ChatContext().append( role="system", text=( "You are a helpful voice assistant powered by Telnyx. " "Keep responses short and conversational." ), ) await ctx.connect(auto_subscribe=AutoSubscribe.AUDIO_ONLY) session = voice.AgentSession( llm=openai.LLM.with_telnyx( model="zai-org/GLM-5.3-Flash", reasoning_effort="high", ), vad=silero.VAD.load(), stt=telnyx.STT(), tts=telnyx.TTS(voice="Telnyx.Ultra.Clara"), chat_ctx=initial_ctx, ) session.start(ctx.room) await session.say("Hey, how can I help you today?", allow_interruptions=True) if __name__ == "__main__": cli.run_app(WorkerOptions(entrypoint_fnc=entrypoint)) ``` ### Set environment variables ```bash export TELNYX_API_KEY= export LIVEKIT_URL= export LIVEKIT_API_KEY= export LIVEKIT_API_SECRET= ``` ### Run the agent worker ```bash python agent.py dev ``` ### Test with a LiveKit frontend Use the [LiveKit Agents Playground](https://agents-playground.livekit.io) to test your agent without building a frontend. ## Telnyx STT & TTS plugin The `livekit-plugins-telnyx` package provides native Telnyx STT and TTS plugins for LiveKit agents. ```bash pip install livekit-plugins-telnyx ``` ### STT Use `telnyx.STT()` for real-time speech-to-text via Telnyx's WebSocket streaming API: ```python from livekit.plugins import telnyx session = voice.AgentSession( stt=telnyx.STT(), # ... other plugins ) ``` ### TTS Use `telnyx.TTS()` for real-time text-to-speech. Pass a `voice` parameter to select a specific voice: ```python from livekit.plugins import telnyx session = voice.AgentSession( tts=telnyx.TTS(voice="Telnyx.Ultra.Clara"), # ... other plugins ) ``` See [TTS available voices](/docs/voice/tts/overview) for the full list of voice options. ## Related resources - [LiveKit Telnyx LLM plugin docs](https://docs.livekit.io/agents/models/llm/plugins/telnyx/) - [SIP trunk configuration for LiveKit](/docs/voice/sip-trunking/livekit-configuration-guide) - [Inference getting started](/docs/inference/models) --- ## Tutorials ### Inference API > Source: https://developers.telnyx.com/docs/inference/getting-started.md ## Prerequisites - [Telnyx account](https://telnyx.com/sign-up) - [API Key](https://portal.telnyx.com/#/app/auth/v2) - Python 3.8+ Install the OpenAI SDK: ```shell pip install openai ``` The Inference API is OpenAI-compatible. Any OpenAI SDK works with a `base_url` swap. ## Python ```python import os from openai import OpenAI client = OpenAI( api_key=os.getenv("TELNYX_API_KEY"), base_url="https://api.telnyx.com/v2/ai/openai", ) chat_completion = client.chat.completions.create( messages=[ {"role": "user", "content": "Tell me about Telnyx"} ], model="zai-org/GLM-5.3-Flash", reasoning_effort="high", stream=True ) # GLM-5.3 Flash is a reasoning model: it streams its thinking in `reasoning_content` # before the final answer in `content`. Print both so you can see the reasoning. reasoning_started = False content_started = False for chunk in chat_completion: delta = chunk.choices[0].delta if getattr(delta, "reasoning_content", None): if not reasoning_started: print("--- reasoning ---") reasoning_started = True print(delta.reasoning_content, end="", flush=True) if delta.content: if not content_started: print("\n--- answer ---") content_started = True print(delta.content, end="", flush=True) ``` Reasoning models such as `zai-org/GLM-5.3-Flash` return their chain-of-thought in a separate `reasoning_content` field (on `message` for non-streaming responses, or `delta` when streaming). Models without reasoning simply omit it, so the `getattr(..., "reasoning_content", None)` guard works for every model. ## Core Concepts ### Messages Chat history passed to the model. ### Roles Every message has a role: **system**, **user**, **assistant**, or **tool**. - **system** — model behavior instructions - **user** — end-user input - **assistant** — model output - **tool** — function call results. See [Function Calling](/docs/inference/functions). ### Models [Available Models](/docs/inference/models) lists all hosted LLMs with context lengths and capabilities. ### Streaming Server-sent events, same as OpenAI. ## What Next? | I want to... | Go to | |:-------------|:------| | Build a voice assistant | [No-Code Voice Assistant](/docs/inference/ai-assistants/no-code-voice-assistant) | | Call custom code from the model | [Function Calling](/docs/inference/functions) / [Streaming Functions](/docs/inference/streaming-functions) | | Ground responses in documents | [Embeddings](/docs/inference/embeddings) | | Identify themes in data | [Clusters](/docs/inference/clusters) | | Migrate from OpenAI | [OpenAI Migration](/docs/inference/openai) | | Browse all models | [Available Models](/docs/inference/models) | --- ### Function Calling > Source: https://developers.telnyx.com/docs/inference/functions.md In this tutorial, you'll learn how to connect large language models to external tools using our [chat completions API](/api-reference/openai-chat/create-a-chat-completion-openai-compatible). This includes: - Defining a function - Enabling the language model to choose the function - Executing the function - Sharing the results with the language model ## Introduction Using the `tools` field, you can enable a language model to choose functions to call. The [chat completions API](/api-reference/openai-chat/create-a-chat-completion-openai-compatible) does not call the function itself. It will return the arguments you need to execute the function yourself. Of the open-source language models hosted on Telnyx, `zai-org/GLM-5.3-Flash` is especially good at calling functions. While we recommend you start with this model, every model in our API supports the `tools` interface. ## Simple `get_current_weather` example A popular toy example for function calls is the `get_current_weather` example. The following code defines a function and passes it to the language model via the `tools` field. Make sure you have set the `TELNYX_API_KEY` environment variable. ```python import os from openai import OpenAI client = OpenAI( api_key=os.getenv("TELNYX_API_KEY"), base_url="https://api.telnyx.com/v2/ai/openai", ) tools = [ { "type": "function", "function": { "name": "get_current_weather", "description": "Get the current weather", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "The city and state, e.g. San Francisco, CA", }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"], "description": "The temperature unit to use", }, }, "required": ["location", "unit"], }, } } ] messages = [ {"role": "user", "content": "How is the weather in Chicago?"} ] chat_completion = client.chat.completions.create( model="zai-org/GLM-5.3-Flash", messages=messages, reasoning_effort="high", tools=tools, tool_choice="auto" ) print(chat_completion.choices[0].message) ``` A `tool_choice` of `auto` lets the language model decide to call a function (or not). The options for `tool_choice` are: - `required`: this forces the language model to choose a tool - `none`: this forces the language model to NOT choose a tool - `auto`: this lets the language model decide If the language model chooses a function, the above will result in a response like this, with the `tool_calls` field populated. ``` ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_c31258d2-78a8-4566-b716-e3b2a774cbdb', function=Function(arguments='{"location": "Chicago", "unit": "fahrenheit"}', name='get_current_weather'), type='function')]) ``` ## Defining functions programmatically In the next example, we will implement and execute `get_current_weather`. To do this cleanly, we are first going to define a helper function `func_to_tool` that extends the `schema` function from Jeremy Howard's [A Hacker's Guide to Language Models](https://github.com/fastai/lm-hackers/blob/main/lm-hackers.ipynb). ```python import inspect import os import json from typing import Literal from openai import OpenAI from pydantic import create_model def func_to_tool(f): kw = { n: (o.annotation, ... if o.default==inspect.Parameter.empty else o.default) for n, o in inspect.signature(f).parameters.items() } s = create_model(f.__name__, **kw).model_json_schema() tool_json = { "type": "function", "function": { "name": s["title"], "description": inspect.getdoc(f), "parameters": s } } return tool_json TempUnit = Literal['celsius', 'fahrenheit'] def get_current_weather(location: str, unit: TempUnit = 'fahrenheit'): """Get the current weather in a given location""" if "tokyo" in location.lower(): return json.dumps({"location": "Tokyo", "temperature": "10", "unit": unit}) elif "san francisco" in location.lower(): return json.dumps({"location": "San Francisco", "temperature": "72", "unit": unit}) elif "chicago" in location.lower(): return json.dumps({"location": "Chicago", "temperature": "22", "unit": unit}) else: return json.dumps({"location": location, "temperature": "unknown"}) client = OpenAI( api_key=os.getenv("TELNYX_API_KEY"), base_url="https://api.telnyx.com/v2/ai/openai", ) tools = [func_to_tool(get_current_weather)] messages = [ {"role": "user", "content": "How is the weather in Chicago?"} ] chat_completion = client.chat.completions.create( model="zai-org/GLM-5.3-Flash", messages=messages, reasoning_effort="high", tools=tools, tool_choice="auto" ) print(chat_completion.choices[0].message) ``` This is now functionally equivalent to the first example, but instead of writing and maintaining the verbose JSON definition ourselves, we can generate it programmatically from the executable Python function. ## Executing functions Ok, it's nice that the language model wants to execute the `get_current_weather`, but how do we actually do that, and incorporate the results back into the interaction? Continuing from the `chat_completion` response in the previous example ```python assistant_message = chat_completion.choices[0].message tool_calls = assistant_message.tool_calls content = assistant_message.content if tool_calls: messages.append(assistant_message) available_functions = {"get_current_weather": get_current_weather} for tool_call in tool_calls: function_name = tool_call.function.name function_to_call = available_functions[function_name] function_args = json.loads(tool_call.function.arguments) function_response = function_to_call(**function_args) messages.append( { "tool_call_id": tool_call.id, "role": "tool", "name": function_name, "content": function_response, } ) second_chat_completion = client.chat.completions.create( model="zai-org/GLM-5.3-Flash", messages=messages, reasoning_effort="high", ) print(second_chat_completion.choices[0].message.content) else: print(content) ``` Now, we will get our answer from the language model, incorporating the output from the function call. ``` It's 22°F in Chicago. ``` --- ### Streaming and Parallel Calls > Source: https://developers.telnyx.com/docs/inference/streaming-functions.md In the [previous tutorial](/docs/inference/functions), we learned the basics for defining and executing functions using our [chat completions API](/api-reference/openai-chat/create-a-chat-completion-openai-compatible). In this tutorial, we will introduce more advanced use cases: - Streaming function calls - Passing multiple functions - Executing function calls in parallel For low-latency contexts, streaming and parallel calls are especially helpful. ## Defining our functions First, we will define two functions we want to execute in parallel: `sleep` and `dream`. Our goal is to use the `dream` function to make an API call to the Telnyx chat completions endpoint while we `sleep`. We will also re-use the `func_to_tool` helped function we defined in the [previous tutorial](/docs/inference/functions) to easily convert between our Python functions and the JSON we need to pass to the `tools` field for our chat completions API. Make sure you have set the `TELNYX_API_KEY` environment variable ```python import asyncio import inspect import json import os from openai import AsyncOpenAI from pydantic import create_model # Configuration API_KEY = os.getenv("TELNYX_API_KEY") BASE_URL = "https://api.telnyx.com/v2/ai/openai" MODEL = "zai-org/GLM-5.3-Flash" client = AsyncOpenAI(api_key=API_KEY, base_url=BASE_URL) async def sleep(seconds: int): """Sleep for a given number of seconds.""" await asyncio.sleep(seconds) return f"I slept for {seconds} seconds!" async def dream(subject: str): """Dream about a given subject.""" chat_completion = await client.chat.completions.create( model=MODEL, reasoning_effort="high", messages=[ { "role": "user", "content": f"BRIEFLY (one sentence max) describe a dream about {subject}" } ] ) return chat_completion.choices[0].message.content def func_to_tool(f): """Convert a function to a tool JSON schema.""" kw = { n: (o.annotation, ... if o.default == inspect.Parameter.empty else o.default) for n, o in inspect.signature(f).parameters.items() } schema = create_model(f.__name__, **kw).model_json_schema() tool_json = { "type": "function", "function": { "name": schema["title"], "description": inspect.getdoc(f), "parameters": schema } } return tool_json ``` ## Parsing Streaming Tools + Executing Tasks in Parallel Next we will define a few functions to help us parse and execute tasks in parallel. ### handle_tool_calls The `handle_tool_calls` function will iterate over streamed chunks from the chat completions endpoint. The language model may invoke multiple tool calls to be executed in parallel and will differentiate them using the `index` attribute on the chunk. As we progress through the stream, we will build our local copy of this list of function calls in the `tool_calls` list. The first chunk of a new tool call will contain the `name` of the function. This enables you to give early feedback to users that a function will be executed. In this example, we simply print the name of the function when it is detected. As we build the arguments from the streamed chunks, we attempt to parse what we have built as JSON. Once we have a valid JSON object, we create an async task to be scheduled for execution (if we have not already done so). **NB: Telnyx guarantees valid JSON is returned for tool calls, so you don't have to worry about lengthy retries or fuzzy matching.** ### execute_tasks This function executes the tasks from the previous function and returns the results as they are completed, enabling users to receive feedback as soon as possible. ### func_wrapper This is a trivial helper function that exposes the tool call ID and function name to `execute_tasks` ```python async def func_wrapper(func, tool_call_id, **kwargs): """Wrap a function to return its ID + name when executed.""" result = await func(**kwargs) return tool_call_id, func.__name__, result async def execute_tasks(tasks): """Execute asynchronous tasks and collect their results.""" results = [] for task in asyncio.as_completed(tasks): tool_call_id, func_name, result = await task print(f"Executed {func_name}, results: {result}") results.append( { "tool_call_id": tool_call_id, "role": "tool", "name": func_name, "content": result, } ) return results async def handle_tool_calls(chat_completion, function_map): """Handle streaming tool calls from chat completion.""" tool_calls = [] tasks = [] tasked_tool_ids = set() async for chunk in chat_completion: delta = chunk.choices[0].delta if delta and delta.tool_calls: # We have detected tool calls from the LLM tcchunklist = delta.tool_calls for tcchunk in tcchunklist: index = tcchunk.index or 0 if len(tool_calls) <= index: # Based on the index, we have a new tool call tool_calls.append( { "id": "", "type": "function", "function": { "name": "", "arguments": "" } } ) tc = tool_calls[index] if tcchunk.id: tc["id"] += tcchunk.id if tcchunk.function.name: tc["function"]["name"] += tcchunk.function.name print(f"Detected function: {tcchunk.function.name}") if tcchunk.function.arguments: tc["function"]["arguments"] += tcchunk.function.arguments try: kwargs = json.loads(tc["function"]["arguments"]) except json.JSONDecodeError: # We don't have the full arguments JSON yet continue else: if tc["id"] not in tasked_tool_ids: func_name = tc["function"]["name"] print(f"Executing {func_name} with {kwargs}") wrapped_func = func_wrapper(function_map[func_name], tc["id"], **kwargs) task = asyncio.create_task(wrapped_func) tasks.append(task) tasked_tool_ids.add(tc["id"]) return tool_calls, tasks ``` ## Putting it all together With our helper functions defined, we are ready to stream and execute multiple function calls in parallel. In this code, we: - Ask the language model to `sleep` and `dream` at the same time - Execute the returned tool calls in parallel - Provide the results back to the language model and get a final response ```python async def main(): prompt = "Take a quick 10 second power nap and dream about Telnyx. Then write a haiku about it!" messages = [{"role": "user", "content": prompt}] print(f"Prompt: {prompt}") functions = [sleep, dream] function_map = {f.__name__: f for f in functions} tools = [func_to_tool(func) for func in functions] chat_completion = await client.chat.completions.create( model=MODEL, messages=messages, reasoning_effort="high", tools=tools, tool_choice="required", stream=True ) tool_calls, tasks = await handle_tool_calls(chat_completion, function_map) messages.append( { "role": "assistant", "tool_calls": tool_calls, } ) task_results = await execute_tasks(tasks) messages.extend(task_results) print("Sending results back to LLM...") print() second_chat_completion = await client.chat.completions.create( model=MODEL, messages=messages, reasoning_effort="high", stream=True, ) # GLM-5.3 Flash is a reasoning model: stream reasoning_content (its thinking) and # content (the final answer) separately. Non-reasoning models omit the former. async for chunk in second_chat_completion: delta = chunk.choices[0].delta if getattr(delta, "reasoning_content", None): print(delta.reasoning_content, end="", flush=True) if delta.content: print(delta.content, end="", flush=True) print() if __name__ == "__main__": asyncio.run(main()) ``` The output of the print statements in this script will look something like this. Notice that `sleep` was detected and executed first, but `dream` still returned results first. ``` Prompt: Take a quick 10 second power nap and dream about Telnyx. Then write a haiku about it! Detected function: sleep Executing sleep with {'seconds': 10} Detected function: dream Executing dream with {'subject': 'Telnyx'} Executed dream, results: In my dream, I was walking through a futuristic cityscape where Telnyx's logo was emblazoned on skyscrapers, and I could hear the hum of millions of concurrent voice calls and messages being transmitted seamlessly through their network. Executed sleep, results: I slept for 10 seconds! Sending results back to LLM... Here is a haiku about Telnyx: Telnyx city glows Voices whisper through the air Connected we stand ``` --- ### JSON Mode and Beyond > Source: https://developers.telnyx.com/docs/inference/json-mode.md In this tutorial, you'll learn how to: * Guarantee structured output using our [chat completions API](/api-reference/openai-chat/create-a-chat-completion-openai-compatible) * This can be done using JSON Schema / Pydantic models, (schemaless) JSON Mode, regular expressions, and multiple choice. ## Sentiment Analysis using Multiple Choice One of the simplest forms of structured output is multiple choice. The only possible outputs of the following code snippet are `positive` or `negative`. Make sure you have set the `TELNYX_API_KEY` environment variable `zai-org/GLM-5.3-Flash` is a reasoning model. Your structured output still arrives in `choices[0].message.content` — the model's chain-of-thought is returned separately in `choices[0].message.reasoning_content`, so it never pollutes the JSON you parse. To surface the reasoning, read it alongside `content`: ```python message = chat_completion.choices[0].message if getattr(message, "reasoning_content", None): print("reasoning:", message.reasoning_content) print(message.content) # the structured output ``` ```python import os from openai import OpenAI client = OpenAI( api_key=os.getenv("TELNYX_API_KEY"), base_url="https://api.telnyx.com/v2/ai/openai", ) chat_completion = client.chat.completions.create( model="zai-org/GLM-5.3-Flash", reasoning_effort="high", messages=[ {"role": "system", "content": "Classify the sentiment of this review as positive or negative."}, {"role": "user", "content": "The staff went above and beyond! I had a great stay."} ], temperature=0.0, extra_body={ "guided_choice": ["positive", "negative"] } ) print(chat_completion.choices[0].message.content) ``` ## Building on this with `guided_json` Now let's say we want to capture an explanation for the classification as well. We can leverage the `guided_json` field for this. ```python import os from openai import OpenAI client = OpenAI( api_key=os.getenv("TELNYX_API_KEY"), base_url="https://api.telnyx.com/v2/ai/openai", ) chat_completion = client.chat.completions.create( model="zai-org/GLM-5.3-Flash", reasoning_effort="high", messages=[ {"role": "system", "content": "First describe the sentiment of the following review and then use that to classify the sentiment as positive or negative."}, {"role": "user", "content": "The staff went above and beyond! I had a great stay."} ], temperature=0.0, extra_body={ "guided_json": { "type": "object", "properties": { "sentiment": { "type": "string", "enum": ["positive", "negative"] }, "explanation": {"type": "string"} }, "required": ["sentiment", "explanation"] } } ) print(chat_completion.choices[0].message.content) ``` This will ensure a JSON response with the same schema as the following ``` { "sentiment": "positive", "explanation": "The review mentions that the staff went above and beyond and the user had a great stay, which indicates a positive sentiment." } ``` ## Simplifying Schema Generation using Pydantic The above is helpful to see the raw JSON Schema specification being sent via API. However, for practical purposes, using Pydantic models can help simplify generating the specs. The following is functionally equivalent to the previous example. ```python import os from enum import Enum from openai import OpenAI from pydantic import BaseModel client = OpenAI( api_key=os.getenv("TELNYX_API_KEY"), base_url="https://api.telnyx.com/v2/ai/openai", ) class Sentiment(str, Enum): positive = 'positive' negative = 'negative' class SentimentAnalysis(BaseModel): explanation: str sentiment: Sentiment chat_completion = client.chat.completions.create( model="zai-org/GLM-5.3-Flash", reasoning_effort="high", messages=[ {"role": "system", "content": "First describe the sentiment of the following review and then use that to classify the sentiment as positive or negative."}, {"role": "user", "content": "The staff went above and beyond! I had a great stay."} ], temperature=0.0, extra_body={ "guided_json": SentimentAnalysis.model_json_schema() } ) print(chat_completion.choices[0].message.content) ``` ## Schema-less JSON Mode We also support the schema-less JSON mode provided by OpenAI ```python import os from openai import OpenAI client = OpenAI( api_key=os.getenv("TELNYX_API_KEY"), base_url="https://api.telnyx.com/v2/ai/openai", ) chat_completion = client.chat.completions.create( model="zai-org/GLM-5.3-Flash", reasoning_effort="high", messages=[ {"role": "system", "content": "First describe the sentiment of the following review and then use that to classify the sentiment as positive or negative. Please respond using a JSON object."}, {"role": "user", "content": "The staff went above and beyond! I had a great stay."} ], temperature=0.0, response_format={"type": "json_object"} ) print(chat_completion.choices[0].message.content) ``` ## And now for something completely different (regular expressions) You can do a lot with regular expressions, and now you can ensure language model outputs follow a regex. Something we see a lot, especially in a voice context, is wanting to limit the length of a response. Below is a toy example limiting a response to a sentence with 20 words or fewer. ```python import os from openai import OpenAI client = OpenAI( api_key=os.getenv("TELNYX_API_KEY"), base_url="https://api.telnyx.com/v2/ai/openai", ) chat_completion = client.chat.completions.create( model="zai-org/GLM-5.3-Flash", reasoning_effort="high", messages=[ {"role": "system", "content": "You are a concise and helpful AI assistant."}, {"role": "user", "content": "Can you tell me about 10DLC?"} ], temperature=0.0, extra_body={ "guided_regex": "(\\w+\\s*){1,20}[\.!?]" } ) print(chat_completion.choices[0].message.content) ``` --- ### Fine Tuning > Source: https://developers.telnyx.com/docs/inference/fine-tuning.md In this tutorial, you'll learn how to: - Upload documents to [Telnyx Storage](https://telnyx.com/products/cloud-storage) - Customize a language model for your unique needs, using those documents - Chat with this fine-tuned language model in the portal or via API Like most fine-tuning providers, Telnyx supports the standard `.jsonl` training file as input. Unlike most fine-tuning providers, Telnyx will also use AI to generate a training file from your raw documents automatically. This is the workflow covered in this tutorial. ## Upload your documents You can upload objects to Telnyx's S3-Compatible storage API using our [quickstart](https://developers.telnyx.com/docs/cloud-storage/quick-start) or with our [drag-and-drop interface in the portal](https://portal.telnyx.com/#/storage/buckets). ![AI Storage Portal](/assets/images/fine-tuning-storage.png) ## Fine-tune a language model on your documents Once you've uploaded your documents, you can [fine tune on them via API](https://developers.telnyx.com/api-reference/fine-tuning/create-a-fine-tuning-job#create-a-fine-tuning-job) or by navigating to the [fine-tuning tab in the portal](https://portal.telnyx.com/#/ai/fine-tuning). Once there you can select a base model to train and the bucket with your training documents. ![AI Fine Tune Creation](/assets/images/fine-tuning-create.png) Behind the scenes, your documents will be automatically converted with AI into a `.jsonl` training file. Immediately after, we will begin fine-tuning your model using this training file. This whole process may take several minutes to complete. You can monitor the status of your fine-tuning job in the fine-tuning tab. ![AI Fine Tune List](/assets/images/fine-tuning-list.png) ## Chat with your new model Once your model is fine-tuned, you can try it out in the [AI Playground in the portal](https://portal.telnyx.com/#/ai/playground) by selecting your model in the dropdown. You can also use your fine-tuned model via our [chat completions API](https://developers.telnyx.com/api-reference/openai-chat/create-a-chat-completion-openai-compatible). Here is a Python example. Make sure you have set the `TELNYX_API_KEY` environment variable. Also, update the `question` and `model` variables in the sample code. ```python import os from openai import OpenAI client = OpenAI( api_key=os.getenv("TELNYX_API_KEY"), base_url="https://api.telnyx.com/v2/ai/openai", ) question = "" model = "" chat_completion = client.chat.completions.create( messages=[ { "role": "user", "content": question } ], model=model, stream=True ) for chunk in chat_completion: if chunk.choices[0].delta.content: print(chunk.choices[0].delta.content, end="", flush=True) ``` --- ### Audio Language Models > Source: https://developers.telnyx.com/docs/inference/audio-language-models.md In this tutorial, you'll learn how to: - Identify which Audio Language Models are available using our [models API](https://developers.telnyx.com/api-reference/openai-chat/get-available-models-openai-compatible) - Chat with open source Audio Language Models using our [chat completions API](/api-reference/openai-chat/create-a-chat-completion-openai-compatible) ## Getting started Audio Language Models are identified in our [models API](https://developers.telnyx.com/api-reference/openai-chat/get-available-models-openai-compatible) with a `task` type of `audio-text-to-text`. Audio is made available to the model in two main ways: - passing a link to the audio in a user message - passing the base64 encoded audio directly in a user message Make sure you have set the TELNYX_API_KEY environment variable ```python import base64 import os from openai import OpenAI import requests client = OpenAI( api_key=os.getenv("TELNYX_API_KEY"), base_url="https://api.telnyx.com/v2/ai/openai" ) def encode_audio_base64_from_url(audio_url: str) -> str: """Encode audio retrieved from a remote url to base64 format.""" with requests.get(audio_url) as response: response.raise_for_status() result = base64.b64encode(response.content).decode('utf-8') return f"data:audio/ogg;base64,{result}" def process_audio(audio_url, instructions): chat_completion = client.chat.completions.create( model="fixie-ai/ultravox-v0_4_1-llama-3_1-8b", messages=[ { "role": "system", "content": instructions }, { "role": "user", "content": [ { "type": "audio_url", "audio_url": { "url": audio_url, }, }, ], } ], ) return chat_completion.choices[0].message.content audio_url = "https://upload.wikimedia.org/wikipedia/commons/e/e0/Phrase_de_Neil_Armstrong.oga" audio_base64 = encode_audio_base64_from_url(audio_url) instructions = "Transcribe this verbatim. Do NOT respond with anything but the transcription." print(f"Transcribe link: {process_audio(audio_url, instructions)}") print(f"Transcribe base64: {process_audio(audio_base64, instructions)}") instructions = "Translate this to French. Be faithful to the original while sounding like a native French speaker. Do NOT respond with anything but the translation." print(f"Translate link: {process_audio(audio_url, instructions)}") ``` This will output something like the following for this audio Your browser does not support the audio element. ``` Transcribe link: That's one small step for man, one giant leap for mankind. Transcribe base64: That's one small step for man, one giant leap for mankind. Translate link: C'est un petit pas pour un homme, un grand pas pour l'humanité. ``` --- ### PR Reviewer - Github Action > Source: https://developers.telnyx.com/docs/inference/pr-reviewer.md ## Introduction Welcome to the PR Reviewer by Telnyx GitHub Action! This guide will teach you how to set up and use the PR Reviewer By Telnyx, which leverages open-source language models running on Telnyx GPUs to automatically review your pull requests. ## Prerequisites - [Sign up for a free Telnyx account](https://telnyx.com/sign-up) if you haven't already. ## Setup guide ### Step 1: Obtain Your Telnyx API Key 1. Log in to your [Telnyx account](https://portal.telnyx.com/). 2. Navigate to the **API Keys** section in the Telnyx portal. 3. Click on **Create API Key**. 4. Copy the generated API key and store it in a secure location. ### Step 2: Add Your Telnyx API Key as a Secret on GitHub 1. In your GitHub repository, go to **Settings** > **Secrets and variables** > **Actions**. 2. Click on **New repository secret**. 3. Name the secret `TELNYX_API_KEY`. 4. Paste your Telnyx API key in the **Value** field and click **Add secret**. ### Step 3: Create the GitHub workflow file To integrate the Telnyx PR Reviewer into your project, follow these steps: 1. In your repository, create a new file at `.github/workflows/review_pr.yml`. 2. Copy and paste the following configuration into the file: ```yaml name: PR Review on: pull_request: types: [opened, synchronize, reopened] permissions: pull-requests: write jobs: review: runs-on: ubuntu-latest steps: - name: PR Review uses: team-telnyx/reviewpr@main with: telnyx_api_key: ${{ secrets.TELNYX_API_KEY }} model_name: "zai-org/GLM-5.3-Flash" ``` 3. Commit the file to your repository. ### Step 4: Optional Configuration The `model_name` parameter in the workflow file is optional. If omitted, the action will use a default language model. If you wish to specify a different model, replace `'meta-llama/Meta-Llama-3.1-8B-Instruct'` with your desired model from the Telnyx [LLM Library](https://telnyx.com/products/llm-library). ## Core Concepts ### GitHub Actions GitHub Actions automate workflows directly in your GitHub repository. In this case, the PR Reviewer By Telnyx is triggered by pull request events, such as when a PR is opened or updated. ### Telnyx Inference API The PR Reviewer By Telnyx uses the Telnyx Inference API to analyze and review the content of pull requests. This API allows interaction with large language models (LLMs) hosted on Telnyx infrastructure. ### Model Selection Your choice of LLM will affect the quality and behavior of the reviews. You can experiment with different models from the Telnyx [LLM Library](https://telnyx.com/products/llm-library) to find the best fit for your project. ### Automatic PR Reviews Once configured, the PR Reviewer By Telnyx automatically generates a review for every pull request based on the content, providing suggestions or feedback powered by the chosen language model. ## Not sure how to get started? | I want to... | Relevant Tutorial | | :------------------------------ | :----------------------------------------------------------------- | | Learn more about GitHub Actions | [GitHub Actions Documentation](https://docs.github.com/en/actions) | | Explore more Telnyx models | [Telnyx LLM Library](https://telnyx.com/products/llm-library) | ## Additional references - Dive into our [Telnyx Inference API documentation](https://developers.telnyx.com/docs/inference) - Explore our full [API reference](/api-reference/openai-chat/create-a-chat-completion-openai-compatible) - Review our [OpenAI Compatibility Matrix](/docs/inference/openai) - Check out our [pricing page](https://telnyx.com/pricing/inference-api) --- ### AI SMS Outfit Recommender with OpenMeteo > Source: https://developers.telnyx.com/docs/inference/ai-outfit-recommender.md Today we will be making a fun script to text us a nice recommendation for outfits based on the weather every morning. It will look something like this at the end: ![Weather Recommendation Screenshot](/assets/images/telnyx-weather-sms-rec.jpg) This project has 3 main components: 1. Check the weather using the free OpenMeteo API 2. Pass the weather info to Telnyx Inference using the model of our choice 3. Send the recommendation to the user using Telnyx SMS Let's get started! ## Checking the weather with OpenMeteo [OpenMeteo](https://open-meteo.com/) is a great free API that allows you to retrieve the forecast for the current day. They have a ton of options for what you can retrieve, but for this demo, we will stick with just the temperature and weather code (although feel free to experiment with other things like humidity!). The following functions can be used to retrieve a weather_description that we can feed into our Telnyx Inference model: ```python def get_weather(latitude, longitude): url = f"https://api.open-meteo.com/v1/forecast?latitude={latitude}&longitude={longitude}¤t=temperature_2m,weathercode&temperature_unit=fahrenheit&timezone=auto" response = requests.get(url) data = response.json() if response.status_code == 200: current = data["current"] temperature = current["temperature_2m"] weathercode = current["weathercode"] weather_description = get_weather_description(weathercode) return f"Temperature: {temperature}°F, {weather_description}" else: return "Failed to fetch weather data" def get_weather_description(code): weather_codes = { 0: "Clear sky", 1: "Mainly clear", 2: "Partly cloudy", 3: "Overcast", 45: "Fog", 48: "Depositing rime fog", 51: "Light drizzle", 53: "Moderate drizzle", 55: "Dense drizzle", 61: "Slight rain", 63: "Moderate rain", 65: "Heavy rain", 71: "Slight snow fall", 73: "Moderate snow fall", 75: "Heavy snow fall", 77: "Snow grains", 80: "Slight rain showers", 81: "Moderate rain showers", 82: "Violent rain showers", 85: "Slight snow showers", 86: "Heavy snow showers", 95: "Thunderstorm", 96: "Thunderstorm with slight hail", 99: "Thunderstorm with heavy hail", } return weather_codes.get(code, "Unknown") ``` It looks like a lot of code, but the majority is just converting the weather codes to a nicely formatted string that the model will be able to understand. Notice also that the longitude and latitude are required to skip the need for an API key, so we will use Chicago's latitude and longitude, 41.9 and 87.6 for this example. ## Getting our recommendation text from Telnyx Inference Now that we have the current weather, let's make a call to Telnyx Inference to generate a text to send to our user. There are [many state-of-the-art open source models available through the Telnyx API](https://telnyx.com/products/llm-library), so for this one we will select [GLM-5.3 Flash from Zhipu AI](https://developers.telnyx.com/docs/inference/models). Let's write a function to retrieve a good weather recommendation from Telnyx Inference. We will just use the `requests` library to not add an additional pip requirement, but the Telnyx LLM API is also compatible with the OpenAI Python and JS SDKs, see the [OpenAI Migration Guide Here](https://developers.telnyx.com/docs/inference/openai). ```python def get_clothing_recommendation(weather_data): url = "https://api.telnyx.com/v2/ai/openai/chat/completions" payload = json.dumps( { "messages": [ { "role": "system", "content": "You are a helpful assistant that texts me every morning with a brief outfit recommendations based on the weather. Be friendly and brief.", }, { "role": "user", "content": f"The weather today is: {weather_data}. What should I wear?", }, ], "model": "zai-org/GLM-5.3-Flash", "reasoning_effort": "high", "max_tokens": 100, } ) headers = { "Content-Type": "application/json", "Accept": "application/json", "Authorization": f"Bearer {os.getenv('TELNYX_API_KEY')}", } response = requests.post(url, headers=headers, data=payload) return response.json()["choices"][0]["message"]["content"] ``` Make sure your `TELNYX_API_KEY` is set in your environment variables so that they can be loaded with `os.getenv('TELNYX_API_KEY')`. The API spec for chat completions can be found here if you would prefer to use HTTP requests instead of the OpenAI client or want to play around with some of the LLM parameters offered. The output of this function will be a string with our recommendation, for example: "Good morning. Perfect day ahead. Why not try a light, pastel-colored short-sleeved shirt, paired with some beige or light-gray shorts? Add some loafers or sneakers, and you're all set for a sunny day. Have a great one!" ## Sending our text to the user Great! Now that we have our weather and text recommendation, we can send the text to the user. Sending a message with Telnyx SMS is easy, follow the [tutorial here if you have not set up a Telnyx number yet](https://developers.telnyx.com/docs/messaging/messages/send-message). We can use the following snippet to send a text using Telnyx: ```python import telnyx telnyx.api_key = os.getenv("TELNYX_API_KEY") def send_sms(to_number, message): return telnyx.Message.create( from_=os.getenv("TELNYX_PHONE_NUMBER"), to=to_number, text=message, ) ``` ## Putting it all together Now that we have all the pieces in place, let's run the script! We can use the following sequence to chain everything together: ```python latitude = 40.7128 # Chicago latitude longitude = -74.0060 # Chicago longitude # Get weather data print("Getting weather data...") weather_description = get_weather(latitude, longitude) print(f"Description received: {weather_description}") to_number = "+1YOUR_DESTINATION_NUMBER" # Example phone number # Get clothing recommendation print("Getting clothing recommendation...") recommendation = get_clothing_recommendation(weather_description) print(f"Recommendation received: {recommendation}") full_text = f"{recommendation}\n\n{weather_description}" # Send SMS print("Sending SMS...") res = send_sms(to_number, full_text) print("SMS sent!") ``` And we see the following output: ``` Getting weather data... Description received: Temperature: 81.8°F, Clear sky Getting clothing recommendation... Recommendation received: Good morning. Perfect day ahead. Why not try a light, pastel-colored short-sleeved shirt, paired with some beige or light-gray shorts? Add some loafers or sneakers, and you're all set for a sunny day. Have a great one! Sending SMS... SMS sent! ``` Great work! We now have our script to send the user weather recommendations based on the weather. To improve this, test out different weather attributes such as humidity to influence the outfit recommendations, or adjust the prompt so the model knows what you generally like to wear or what you have in your closet. You could also run this script automatically every day at a certain time using a `cronjob` or the task scheduler of your choice. Thanks for following along! --- ## API Reference (Inference) ### OpenAI Chat - [Create a chat completion (OpenAI-compatible)](https://developers.telnyx.com/api-reference/openai-chat/create-a-chat-completion-openai-compatible.md): Chat with a language model. This endpoint is consistent with the OpenAI Chat Completions API and may be used with the OpenAI JS or Python SDK by setting the ba… - [Get available models (OpenAI-compatible)](https://developers.telnyx.com/api-reference/openai-chat/get-available-models-openai-compatible.md): Lists every model currently available to your account on Telnyx Inference, including SOTA open-source LLMs hosted on Telnyx GPUs (for example `moonshotai/Kimi-… - [Create an OpenAI-compatible response](https://developers.telnyx.com/api-reference/openai-chat/create-an-openai-compatible-response.md): Create a response using Telnyx's OpenAI-compatible Responses API. This endpoint is compatible with the OpenAI Responses API and may be used with the OpenAI JS… ### Fine Tuning - [List fine tuning jobs](https://developers.telnyx.com/api-reference/fine-tuning/list-fine-tuning-jobs.md): Retrieve a list of all fine tuning jobs created by the user. - [Create a fine tuning job](https://developers.telnyx.com/api-reference/fine-tuning/create-a-fine-tuning-job.md): Creates a new fine-tuning job that trains a model on the provided dataset, and returns the created job. - [Get a fine tuning job](https://developers.telnyx.com/api-reference/fine-tuning/get-a-fine-tuning-job.md): Returns the details of a single fine-tuning job by its job_id, including its current status. - [Cancel a fine tuning job](https://developers.telnyx.com/api-reference/fine-tuning/cancel-a-fine-tuning-job.md): Cancels the specified in-progress fine-tuning job and returns the updated job. ### Anthropic Messages - [Create a message (Anthropic-compatible)](https://developers.telnyx.com/api-reference/anthropic-messages/create-a-message-anthropic-compatible.md): Send a message to a language model using the Anthropic Messages API format. This endpoint is compatible with the Anthropic Messages API and may be used with th… ### Chat - [Summarize file content](https://developers.telnyx.com/api-reference/chat/summarize-file-content.md): Generate a summary of a file's contents.