Skip to content
Docs

Python with AI Gateway: OpenAI and Anthropic SDKs

To get started with Python and AI Gateway, you can either call the OpenAI Chat Completions, OpenAI Responses, or Anthropic Messages API directly, or use the official OpenAI and Anthropic Python SDKs, which are covered below.

You can also use the AI SDK for Python. It's currently in public beta.

Install your preferred SDK:

pip install openai
pip install anthropic
pip install openai
quickstart.py
import os
from openai import OpenAI
 
client = OpenAI(
    api_key=os.getenv('AI_GATEWAY_API_KEY'),
    base_url='https://ai-gateway.vercel.sh/v1'
)
 
response = client.chat.completions.create(
    model='anthropic/claude-opus-5',
    messages=[
        {'role': 'user', 'content': 'Explain quantum computing in one paragraph.'}
    ]
)
 
print(response.choices[0].message.content)
quickstart.py
import os
import anthropic
 
client = anthropic.Anthropic(
    api_key=os.getenv('AI_GATEWAY_API_KEY'),
    base_url='https://ai-gateway.vercel.sh'
)
 
message = client.messages.create(
    model='anthropic/claude-opus-5',
    max_tokens=1024,
    messages=[
        {'role': 'user', 'content': 'Explain quantum computing in one paragraph.'}
    ]
)
 
for block in message.content:
    if block.type == "text":
        print(block.text)
quickstart.py
import os
from openai import OpenAI
 
client = OpenAI(
    api_key=os.getenv('AI_GATEWAY_API_KEY'),
    base_url='https://ai-gateway.vercel.sh/v1',
)
 
response = client.responses.create(
    model='anthropic/claude-opus-5',
    input='Explain quantum computing in one paragraph.',
)
 
print(response.output_text)

All SDKs support the same authentication methods. Use an API key for local development or OIDC tokens for Vercel deployments.

auth.py
import os
 
# Option 1: API key (recommended for local development)
api_key = os.getenv('AI_GATEWAY_API_KEY')
 
# Option 2: OIDC token (automatic on Vercel deployments)
api_key = os.getenv('VERCEL_OIDC_TOKEN')
 
# Fallback pattern for code that runs both locally and on Vercel
api_key = os.getenv('AI_GATEWAY_API_KEY') or os.getenv('VERCEL_OIDC_TOKEN')

Stream responses for real-time output in chat applications or long-running generations.

streaming.py
import os
from openai import OpenAI
 
client = OpenAI(
    api_key=os.getenv('AI_GATEWAY_API_KEY'),
    base_url='https://ai-gateway.vercel.sh/v1'
)
 
stream = client.chat.completions.create(
    model='anthropic/claude-opus-5',
    messages=[
        {'role': 'user', 'content': 'Write a short story about a robot.'}
    ],
    stream=True
)
 
for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end='', flush=True)
streaming.py
import os
import anthropic
 
client = anthropic.Anthropic(
    api_key=os.getenv('AI_GATEWAY_API_KEY'),
    base_url='https://ai-gateway.vercel.sh'
)
 
with client.messages.stream(
    model='anthropic/claude-opus-5',
    max_tokens=1024,
    messages=[
        {'role': 'user', 'content': 'Write a short story about a robot.'}
    ]
) as stream:
    for text in stream.text_stream:
        print(text, end='', flush=True)
streaming.py
import os
from openai import OpenAI
 
client = OpenAI(
    api_key=os.getenv('AI_GATEWAY_API_KEY'),
    base_url='https://ai-gateway.vercel.sh/v1',
)
 
stream = client.responses.create(
    model='anthropic/claude-opus-5',
    input='Write a short story about a robot.',
    stream=True,
)
 
for event in stream:
    if event.type == 'response.output_text.delta':
        print(event.delta, end='', flush=True)

Both the OpenAI and Anthropic SDKs provide async clients for use with asyncio.

async_client.py
import os
import asyncio
from openai import AsyncOpenAI
 
client = AsyncOpenAI(
    api_key=os.getenv('AI_GATEWAY_API_KEY'),
    base_url='https://ai-gateway.vercel.sh/v1'
)
 
async def main():
    response = await client.chat.completions.create(
        model='anthropic/claude-opus-5',
        messages=[
            {'role': 'user', 'content': 'Hello!'}
        ]
    )
    print(response.choices[0].message.content)
 
asyncio.run(main())
async_client.py
import os
import asyncio
import anthropic
 
client = anthropic.AsyncAnthropic(
    api_key=os.getenv('AI_GATEWAY_API_KEY'),
    base_url='https://ai-gateway.vercel.sh'
)
 
async def main():
    message = await client.messages.create(
        model='anthropic/claude-opus-5',
        max_tokens=1024,
        messages=[
            {'role': 'user', 'content': 'Hello!'}
        ]
    )
    for block in message.content:
        if block.type == "text":
            print(block.text)
 
asyncio.run(main())
async_client.py
import os
import asyncio
from openai import AsyncOpenAI
 
client = AsyncOpenAI(
    api_key=os.getenv('AI_GATEWAY_API_KEY'),
    base_url='https://ai-gateway.vercel.sh/v1',
)
 
async def main():
    response = await client.responses.create(
        model='anthropic/claude-opus-5',
        input='Hello!',
    )
    print(response.output_text)
 
asyncio.run(main())

Enable models to call functions you define. This example shows a weather tool that the model can invoke.

tools.py
import os
import json
from openai import OpenAI
 
client = OpenAI(
    api_key=os.getenv('AI_GATEWAY_API_KEY'),
    base_url='https://ai-gateway.vercel.sh/v1'
)
 
tools = [{
    'type': 'function',
    'function': {
        'name': 'get_weather',
        'description': 'Get the current weather for a location',
        'parameters': {
            'type': 'object',
            'properties': {
                'location': {
                    'type': 'string',
                    'description': 'City name, e.g. San Francisco'
                }
            },
            'required': ['location']
        }
    }
}]
 
response = client.chat.completions.create(
    model='anthropic/claude-opus-5',
    messages=[
        {'role': 'user', 'content': "What's the weather in Tokyo?"}
    ],
    tools=tools
)
 
# Check if the model wants to call a tool
if response.choices[0].message.tool_calls:
    tool_call = response.choices[0].message.tool_calls[0]
    args = json.loads(tool_call.function.arguments)
    print(f"Model wants to call: {tool_call.function.name}")
    print(f"With arguments: {args}")
tools.py
import os
import anthropic
 
client = anthropic.Anthropic(
    api_key=os.getenv('AI_GATEWAY_API_KEY'),
    base_url='https://ai-gateway.vercel.sh'
)
 
tools = [{
    'name': 'get_weather',
    'description': 'Get the current weather for a location',
    'input_schema': {
        'type': 'object',
        'properties': {
            'location': {
                'type': 'string',
                'description': 'City name, e.g. San Francisco'
            }
        },
        'required': ['location']
    }
}]
 
message = client.messages.create(
    model='anthropic/claude-opus-5',
    max_tokens=1024,
    messages=[
        {'role': 'user', 'content': "What's the weather in Tokyo?"}
    ],
    tools=tools
)
 
# Check if the model wants to call a tool
for block in message.content:
    if block.type == 'tool_use':
        print(f"Model wants to call: {block.name}")
        print(f"With arguments: {block.input}")
tools.py
import os
from openai import OpenAI
 
client = OpenAI(
    api_key=os.getenv('AI_GATEWAY_API_KEY'),
    base_url='https://ai-gateway.vercel.sh/v1',
)
 
response = client.responses.create(
    model='openai/gpt-6-astra',
    input='What is the weather in Tokyo?',
    tools=[
        {
            'type': 'function',
            'name': 'get_weather',
            'description': 'Get the current weather for a location',
            'parameters': {
                'type': 'object',
                'properties': {
                    'location': {'type': 'string'},
                },
                'required': ['location'],
            },
        },
    ],
)
 
for item in response.output:
    if item.type == 'function_call':
        print(f'Call: {item.name}({item.arguments})')

See Chat Completions tool calls, OpenAI Responses API tool calling, or Anthropic Messages tool calls for more examples.

Generate responses that conform to a JSON schema for reliable parsing.

structured.py
import os
from openai import OpenAI
 
client = OpenAI(
    api_key=os.getenv('AI_GATEWAY_API_KEY'),
    base_url='https://ai-gateway.vercel.sh/v1'
)
 
response = client.chat.completions.create(
    model='anthropic/claude-opus-5',
    messages=[
        {'role': 'user', 'content': 'Extract: John is 30 years old and lives in NYC'}
    ],
    response_format={
        'type': 'json_schema',
        'json_schema': {
            'name': 'person',
            'schema': {
                'type': 'object',
                'properties': {
                    'name': {'type': 'string'},
                    'age': {'type': 'integer'},
                    'city': {'type': 'string'}
                },
                'required': ['name', 'age', 'city']
            }
        }
    }
)
 
import json
data = json.loads(response.choices[0].message.content)
print(data)  # {'name': 'John', 'age': 30, 'city': 'NYC'}

See structured outputs for more details.

Each surface takes attachments as an array of content parts in place of a plain string, but the part names differ. Read the file, base64-encode it, and use the shape for your surface:

vision.py
import base64
import os
from openai import OpenAI
 
client = OpenAI(
    api_key=os.getenv('AI_GATEWAY_API_KEY'),
    base_url='https://ai-gateway.vercel.sh/v1'
)
 
with open('diagram.png', 'rb') as f:
    image_base64 = base64.b64encode(f.read()).decode()
 
completion = client.chat.completions.create(
    model='anthropic/claude-opus-5',
    messages=[
        {
            'role': 'user',
            'content': [
                {'type': 'text', 'text': 'Describe this image in one sentence.'},
                {
                    'type': 'image_url',
                    'image_url': {'url': f'data:image/png;base64,{image_base64}'}
                }
            ]
        }
    ]
)
 
print(completion.choices[0].message.content)
vision.py
import base64
import os
import anthropic
 
client = anthropic.Anthropic(
    api_key=os.getenv('AI_GATEWAY_API_KEY'),
    base_url='https://ai-gateway.vercel.sh'
)
 
with open('diagram.png', 'rb') as f:
    image_base64 = base64.b64encode(f.read()).decode()
 
message = client.messages.create(
    model='anthropic/claude-opus-5',
    max_tokens=1024,
    messages=[
        {
            'role': 'user',
            'content': [
                {'type': 'text', 'text': 'Describe this image in one sentence.'},
                {
                    'type': 'image',
                    'source': {
                        'type': 'base64',
                        'media_type': 'image/png',
                        'data': image_base64
                    }
                }
            ]
        }
    ]
)
 
for block in message.content:
    if block.type == "text":
        print(block.text)
vision.py
import base64
import os
from openai import OpenAI
 
client = OpenAI(
    api_key=os.getenv('AI_GATEWAY_API_KEY'),
    base_url='https://ai-gateway.vercel.sh/v1'
)
 
with open('diagram.png', 'rb') as f:
    image_base64 = base64.b64encode(f.read()).decode()
 
response = client.responses.create(
    model='anthropic/claude-opus-5',
    input=[
        {
            'role': 'user',
            'content': [
                {'type': 'input_text', 'text': 'Describe this image in one sentence.'},
                {
                    'type': 'input_image',
                    'image_url': f'data:image/png;base64,{image_base64}'
                }
            ]
        }
    ]
)
 
print(response.output_text)

PDFs work the same way with a different part type. On Anthropic Messages that is a document part:

pdf.py
import base64
import os
import anthropic
 
client = anthropic.Anthropic(
    api_key=os.getenv('AI_GATEWAY_API_KEY'),
    base_url='https://ai-gateway.vercel.sh'
)
 
with open('report.pdf', 'rb') as f:
    pdf_base64 = base64.b64encode(f.read()).decode()
 
message = client.messages.create(
    model='anthropic/claude-opus-5',
    max_tokens=1024,
    messages=[
        {
            'role': 'user',
            'content': [
                {'type': 'text', 'text': 'What total does this document state?'},
                {
                    'type': 'document',
                    'source': {
                        'type': 'base64',
                        'media_type': 'application/pdf',
                        'data': pdf_base64
                    }
                }
            ]
        }
    ]
)

For the per-surface reference, see Chat Completions file attachments, Responses file attachments, and Anthropic file attachments.

Reasoning models work through a problem before answering. On the Responses API, pass reasoning with an effort level:

reasoning.py
import os
from openai import OpenAI
 
client = OpenAI(
    api_key=os.getenv('AI_GATEWAY_API_KEY'),
    base_url='https://ai-gateway.vercel.sh/v1',
)
 
response = client.responses.create(
    model='openai/gpt-6-astra',
    input='Explain the Monty Hall problem step by step.',
    reasoning={'effort': 'medium'},
    max_output_tokens=2048,
)
 
print(response.output_text)

The Chat Completions API takes the same idea through extra_body, since the OpenAI Python client does not have a typed field for it:

reasoning-chat-completions.py
import os
from openai import OpenAI
 
client = OpenAI(
    api_key=os.getenv('AI_GATEWAY_API_KEY'),
    base_url='https://ai-gateway.vercel.sh/v1',
)
 
completion = client.chat.completions.create(
    model='openai/gpt-6-astra',
    messages=[{'role': 'user', 'content': 'Explain the Monty Hall problem.'}],
    extra_body={'reasoning': {'effort': 'medium'}},
)
 
print(completion.choices[0].message.reasoning)
print(completion.choices[0].message.content)

Each surface names and shapes this differently, and Anthropic models have their own constraints. See Responses reasoning, Chat Completions reasoning, and Anthropic extended thinking.

Python frameworks with dedicated AI Gateway support:

FrameworkIntegration
Pydantic AINative VercelProvider for type-safe agents
LlamaIndexllama-index-llms-vercel-ai-gateway package
LiteLLMUse vercel_ai_gateway/ model prefix
LangChainConfigure via Chat Completions endpoint

See Framework Integrations for the complete list and setup guides.

For complete API documentation, see:

Last updated September 8, 2026

Was this helpful?

supported.