# OpenAI Agents SDK

> OpenAI Agents SDK (Python ও TypeScript) দিয়ে বানানো agent Tokens-এ চালান: Chat Completions model class, model ID-র slash-এর সমস্যা, tracing, tool আর streaming।

OpenAI Agents SDK হলো agent বানানোর জন্য OpenAI-র library। এখানে একটা `Agent`-এ instructions আর tool দেওয়া থাকে, আর সেটা চালায় একটা `Runner`। SDK model-এর সাথে কথা বলে OpenAI API দিয়ে, তাই `https://tokens.bd/v1` ঠিকানায় সে Tokens-এও পৌঁছাতে পারে। শুধু দুটো default পথে বাধা হয়, দুটোই সহজে ঠিক করা যায়। এক, আলাদা করে না বললে SDK Responses API ডাকে। দুই, model ID-তে slash থাকলে সে সেটাকে `provider/model` ধরে নেয়। Tokens-এর প্রতিটা model ID-তেই slash আছে, তাই এই পেজে দুটো জিনিসই কীভাবে সাজাতে হয় দেখানো হয়েছে।

:::note[Documentation-এর সাথে মিলিয়ে দেখা]
এই গাইড OpenAI Agents SDK-র documentation থেকে নেওয়া। October 2026-এ মিলিয়ে দেখা হয়েছে Python package `openai-agents` 0.23.1 (প্রকাশ 2 October 2026) আর TypeScript package `@openai/agents` 0.20.0-এর সাথে। code-টা documentation আর SDK-র নিজের উদাহরণের সাথে মিলিয়ে দেখা হয়েছে, Tokens-এর বিরুদ্ধে শুরু থেকে শেষ পর্যন্ত চালিয়ে দেখা হয়নি। SDK দ্রুত বদলায়। তাই আপনার version-এর সাথে কিছু না মিললে [official docs](https://openai.github.io/openai-agents-python/models/) দেখে নিন।
:::

## যা যা লাগবে

- [API keys](/docs/api-keys) থেকে নেওয়া একটা Tokens key, যেটা `TOKENS_API_KEY` নামে export করা।
- [/models](/models) থেকে একটা model ID, যেমন `deepseek/deepseek-v4.1-flash`। Agent tool ডাকে, তাই এমন model নিন যেটা tool calling সাপোর্ট করে ([Choosing a model](/docs/choosing-a-model))।
- Python package-এর জন্য Python 3.10 বা তার পরের version। TypeScript package-এ নিজের client দিলে `openai` package-এর version 7.2 বা তার পরের হতে হবে।

```bash
export TOKENS_API_KEY="tok_live_your_key"
```

## কেন default বদলাতে হয়

| SDK-র default                                | Tokens-এ কী হয়                                                                                                                                                                  | সমাধান                                                                                           |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| Responses API ব্যবহার করে                     | Tokens `/v1/responses` পাস করে দেয়, কিন্তু সেটা চলে শুধু তখনই যখন model-এর পেছনের provider নিজে এটা সাপোর্ট করে ([Responses](/docs/responses))। Chat Completions সব model-এ চলে। | `OpenAIChatCompletionsModel` নিন, অথবা `set_default_openai_api("chat_completions")` দিন।         |
| `prefix/name`-কে provider prefix ধরে নেয়     | SDK-র documentation বলছে, অচেনা prefix হলে `UserError` ওঠে, আর `openai/...` হলে slash-এর পরের অংশটুকু রেখে বাকিটা ছেঁটে দেওয়া হয়। `deepseek/deepseek-v4.1-flash`-এর মতো Tokens ID এই নিয়মে আটকে যায়। | model object দিন, custom `ModelProvider` ব্যবহার করুন, অথবা prefix mode বদলে দিন।                |
| Trace OpenAI-তে upload করে                   | Trace চলে OpenAI-র server-এ, আর তার জন্য OpenAI key লাগে। Tokens key দিলে upload-এ `401` হয়, যা আপনার log-এ দেখা যাবে।                                                          | Tracing বন্ধ করুন।                                                                               |

SDK-র documentation এগুলো রেখেছে "non-OpenAI models" অংশে। যে provider-এ Responses নেই, সেখানে সে Chat Completions ব্যবহার করতে বলে। আর স্পষ্ট বলে, অচেনা prefix pass-through হয় না, `UserError` ওঠে।

## Python: Chat Completions model object ব্যবহার করুন

শুরুতে এই setup-টাই নিন। Tokens-এর দিকে তাক করা একটা `AsyncOpenAI` client বানাতে হবে, সেটাকে `OpenAIChatCompletionsModel`-এ মুড়ে agent-এর হাতে দিতে হবে। Agent model-এর নাম (string) না পেয়ে একটা model object পায়, তাই SDK model ID parse করে না। ফলে slash নিয়ে কোনো সমস্যাই হয় না।

```bash
pip install --upgrade openai-agents
```

```python title="agent.py"
import asyncio
import os

from openai import AsyncOpenAI
from agents import Agent, OpenAIChatCompletionsModel, Runner, set_tracing_disabled

set_tracing_disabled(True)  # traces would go to OpenAI; see the Tracing section

client = AsyncOpenAI(
    base_url="https://tokens.bd/v1",
    api_key=os.environ["TOKENS_API_KEY"],
)

agent = Agent(
    name="Reviewer",
    instructions="You are a concise senior engineer. Answer in at most three sentences.",
    model=OpenAIChatCompletionsModel(model="deepseek/deepseek-v4.1-flash", openai_client=client),
)


async def main() -> None:
    result = await Runner.run(agent, "When should I use a dataclass instead of a dict?")
    print(result.final_output)


asyncio.run(main())
```

`base_url`-এর শেষে `/v1` রাখুন। model string-টা Tokens-এ যেমন লেখা তেমনই যায়, তাই সেটা [/models](/models)-এর কোনো ID-র সাথে বা `GET https://tokens.bd/v1/models`-এর সাথে হুবহু মিলতে হবে।

## Python: এক জায়গা থেকে সব agent-এর model ঠিক করুন

অনেক agent থাকলে `RunConfig`-এর ভেতর দিয়ে একটা custom `ModelProvider` দিন। তাহলে পুরো run-এ একই model setup খাটে, আর `Agent` object-এ সাধারণ model নামই রাখা যায়। এটা SDK-র নিজের `custom_example_provider.py` উদাহরণ মেনে লেখা।

```python title="provider.py"
import asyncio
import os

from openai import AsyncOpenAI
from agents import (
    Agent,
    Model,
    ModelProvider,
    OpenAIChatCompletionsModel,
    RunConfig,
    Runner,
    set_tracing_disabled,
)

set_tracing_disabled(True)

client = AsyncOpenAI(
    base_url="https://tokens.bd/v1",
    api_key=os.environ["TOKENS_API_KEY"],
)


class TokensModelProvider(ModelProvider):
    def get_model(self, model_name: str | None) -> Model:
        # The name arrives untouched, slash included.
        return OpenAIChatCompletionsModel(
            model=model_name or "deepseek/deepseek-v4.1-flash",
            openai_client=client,
        )


agent = Agent(
    name="Assistant",
    instructions="You are a helpful assistant.",
    model="deepseek/deepseek-v4.1-flash",
)


async def main() -> None:
    result = await Runner.run(
        agent,
        "Name two uses for asyncio.Semaphore.",
        run_config=RunConfig(model_provider=TokensModelProvider()),
    )
    print(result.final_output)


asyncio.run(main())
```

`RunConfig` শুধু ওই একটা `Runner.run` call-এর জন্য খাটে। এটা ছাড়া run করলে request চলে OpenAI-র নিজের endpoint-এ, আর `OPENAI_API_KEY` যা সেট করা আছে সেটাই ব্যবহার হয়।

### বিকল্প: global client

SDK-তে একটা global default-ও আছে। সব agent-ই Tokens ব্যবহার করবে, এমন হলে এটাই সবচেয়ে ছোট setup:

```python
import os
from openai import AsyncOpenAI
from agents import set_default_openai_api, set_default_openai_client, set_tracing_disabled

set_default_openai_client(
    AsyncOpenAI(base_url="https://tokens.bd/v1", api_key=os.environ["TOKENS_API_KEY"]),
    use_for_tracing=False,
)
set_default_openai_api("chat_completions")
set_tracing_disabled(True)
```

এই setup-এও `model="deepseek/deepseek-v4.1-flash"`-এর মতো সাধারণ string চলে যায় SDK-র default `MultiProvider`-এর ভেতর দিয়ে, আর সে প্রথম slash-এ ভেঙে ফেলে। Slash-এর আগের অংশটা SDK-র চেনা কোনো provider নয়, তাই default আচরণ হলো `UserError: Unknown prefix` ছোঁড়া। আর prefix যদি `openai` হয়, SDK কোনো শব্দ না করে শুধু slash-এর পরের অংশটা পাঠায়। Global setup-এর সাথে model string ব্যবহার করতে চাইলে provider নিজে বানান আর তাকে বলে দিন পুরো ID রেখে দিতে:

```python
import os
from agents import MultiProvider, RunConfig

provider = MultiProvider(
    openai_base_url="https://tokens.bd/v1",
    openai_api_key=os.environ["TOKENS_API_KEY"],
    openai_use_responses=False,         # Chat Completions
    openai_prefix_mode="model_id",      # keep a leading "openai/" as part of the id
    unknown_prefix_mode="model_id",     # keep any other "provider/" as part of the id
)

run_config = RunConfig(model_provider=provider)
```

`openai_prefix_mode` আর `unknown_prefix_mode` SDK-তে আছে `openrouter/openai/gpt-4.1-mini`-র মতো namespace-ওয়ালা ID কোনো OpenAI-compatible backend-এ পাঠানোর জন্য। তবে model object বা ওপরের `ModelProvider`-এর মতো সহজ পথে এই প্রশ্নটাই ওঠে না, তাই ওগুলোকেই বেছে নিন।

:::note
`use_for_tracing=False` দিলে SDK এই client-এর key (মানে আপনার Tokens key) দিয়ে OpenAI-তে trace upload করা বন্ধ করে। এর default `True`। এই argument-টার কথা আছে SDK-র source docstring-এ, তার guide পেজগুলোতে নেই। তাই যে version install করছেন তার সাথে মিলিয়ে নিন।
:::

## Tracing: বন্ধ করে দিন

SDK default-ভাবে trace OpenAI-র server-এ upload করে। OpenAI platform key না থাকলে agent ঠিকমতো চললেও log-এ `401` error আসতে থাকে। Documentation-এ tracing বন্ধ করার তিনটে উপায় আছে:

| কতটুকু জায়গা জুড়ে | কীভাবে                                                                                         |
| ------------------- | ---------------------------------------------------------------------------------------------- |
| পুরো process        | `set_tracing_disabled(True)`, অথবা environment variable `OPENAI_AGENTS_DISABLE_TRACING=1` |
| একটা run            | `RunConfig(tracing_disabled=True)`                                                             |

Tracing চালু রেখে শুধু upload-এর জন্য আলাদা একটা OpenAI key দিতে চাইলে `set_tracing_export_api_key(...)` আছে। সেই key আনতে হবে platform.openai.com থেকে। ওটা আপনার Tokens key নয়, আর তখন আপনার prompt trace data হয়ে OpenAI-তে চলে যাবে। Prompt গোপন হলে tracing বন্ধই রাখুন।

## Tool

Agent-কে দিন type hint আর docstring-ওয়ালা Python function। এগুলো থেকেই SDK tool-এর schema বানিয়ে নেয়।

```python title="tools.py"
import asyncio
import os

from openai import AsyncOpenAI
from agents import (
    Agent,
    OpenAIChatCompletionsModel,
    Runner,
    function_tool,
    set_tracing_disabled,
)

set_tracing_disabled(True)

client = AsyncOpenAI(
    base_url="https://tokens.bd/v1",
    api_key=os.environ["TOKENS_API_KEY"],
)


@function_tool
def get_weather(city: str) -> str:
    """Current weather for a city.

    Args:
        city: The city to look up.
    """
    return f"{city}: light rain, 29C"  # replace with a real lookup


agent = Agent(
    name="Weather helper",
    instructions="Use the tool when the user asks about the weather.",
    model=OpenAIChatCompletionsModel(model="deepseek/deepseek-v4.1-flash", openai_client=client),
    tools=[get_weather],
)


async def main() -> None:
    result = await Runner.run(agent, "Do I need an umbrella in Dhaka?")
    print(result.final_output)


asyncio.run(main())
```

প্রকাশিত package-এ decorator-টার নাম `function_tool`। SDK-র নতুন documentation একই decorator import করে `from agents.decorators import tool` দিয়ে, যেটা ওর alias। যে version মিলিয়ে দেখা হয়েছে তাতে দুটোই চলে।

প্রতিটা tool call মানে Tokens-এ আরেকটা request। তাই কয়েক রাউন্ড tool চললে কয়েকটা request খরচ হয়, আর সেগুলো আপনার [rate limits](/docs/rate-limits)-এর হিসাবে পড়ে। Tool calling-এর জন্য এমন model লাগে যেটা তা সাপোর্ট করে ([Tool calling](/docs/tool-calling))।

SDK-র documentation-এ কিছু tool আছে যেগুলো শুধু Responses API-তে চলে (যেমন `ToolSearchTool`), আর বলা আছে Chat Completions backend সেগুলো ফিরিয়ে দেয়। Web search বা file search-এর মতো hosted tool চলে OpenAI-র নিজের দিকে, তাই Tokens দিয়ে সেগুলো পাওয়া যায় না।

## Output stream করুন

`Runner.run_streamed` এমন একটা result দেয় যার ওপর loop চালিয়ে event পাওয়া যায়। SDK-র documentation-এ দেওয়া text streaming-এর loop এটাই:

```python title="stream.py"
import asyncio
import os

from openai import AsyncOpenAI
from openai.types.responses import ResponseTextDeltaEvent
from agents import Agent, OpenAIChatCompletionsModel, Runner, set_tracing_disabled

set_tracing_disabled(True)

client = AsyncOpenAI(
    base_url="https://tokens.bd/v1",
    api_key=os.environ["TOKENS_API_KEY"],
)

agent = Agent(
    name="Writer",
    instructions="You write short, plain answers.",
    model=OpenAIChatCompletionsModel(model="deepseek/deepseek-v4.1-flash", openai_client=client),
)


async def main() -> None:
    result = Runner.run_streamed(agent, input="Write a haiku about merge conflicts.")
    async for event in result.stream_events():
        if event.type == "raw_response_event" and isinstance(event.data, ResponseTextDeltaEvent):
            print(event.data.delta, end="", flush=True)
    print()


asyncio.run(main())
```

Stream শেষ না হওয়া পর্যন্ত পড়তে থাকুন। Iterator শেষ না হলে run-ও শেষ হয় না। SDK-র streaming পেজে এই loop দেখানো হয়েছে default setup-এর জন্য। `OpenAIChatCompletionsModel`-এ একই রকম চলবে কিনা সেটা সেখানে বলা নেই, তাই আপনার model দিয়ে একবার test করে নিন। আরও দেখুন [Streaming](/docs/streaming)।

Tokens-এর stream-এ token-এর হিসাব আসে শুধু তখনই, যখন request-এ সেটা চাওয়া হয়। Chat Completions-এ এর জন্য SDK-তে `ModelSettings(include_usage=True)` field আছে (documentation অনুযায়ী field-টা শুধু Chat Completions-এ পাওয়া যায়)। `agents` থেকে `ModelSettings` import করুন আর দিন এভাবে: `Agent(..., model_settings=ModelSettings(include_usage=True))`।

কোনো provider streaming-এর সময় ভাঙা tool-call-এর টুকরো পাঠালে SDK-র একটা option আছে, `MultiProvider`-এ `openai_buffer_streamed_tool_calls=True`, যেটা সেগুলো জমিয়ে রাখে।

## TypeScript

TypeScript package-এর নাম `@openai/agents`। এর peer dependency হিসেবে `zod` 4 লাগে, আর নিজের client দিলে `openai` package-ও (version 7.2 বা তার পরের)।

```bash
npm install @openai/agents zod openai
```

```ts title="agent.ts"
import OpenAI from "openai";
import {
  Agent,
  OpenAIChatCompletionsModel,
  run,
  setTracingDisabled,
  tool,
} from "@openai/agents";
import { z } from "zod";

setTracingDisabled(true);

const client = new OpenAI({
  apiKey: process.env.TOKENS_API_KEY,
  baseURL: "https://tokens.bd/v1",
});

const getWeather = tool({
  name: "get_weather",
  description: "Current weather for a city",
  parameters: z.object({ city: z.string() }),
  async execute({ city }) {
    return `${city}: light rain, 29C`; // replace with a real lookup
  },
});

const agent = new Agent({
  name: "Weather helper",
  instructions: "Use the tool when the user asks about the weather.",
  model: new OpenAIChatCompletionsModel(client, "deepseek/deepseek-v4.1-flash"),
  tools: [getWeather],
});

const result = await run(agent, "Do I need an umbrella in Dhaka?");
console.log(result.finalOutput);
```

`OpenAIChatCompletionsModel`-এর একটা instance দিলে ওই agent Chat Completions-এই থাকে, আর model ID parse হয় না। SDK-র নিজের উদাহরণে আরও দুটো পথ আছে: `setOpenAIAPI("chat_completions")`-এর সাথে `setDefaultOpenAIClient(client)` দিয়ে global পথ, আর `OpenAIProvider({ openAIClient: client })` দিয়ে `new Runner({ modelProvider })` পথ। এই পথগুলো slash-ওয়ালা model নাম কীভাবে সামলায়, TypeScript documentation-এ তা বলা নেই। তাই ওপরের model object-টাই ব্যবহার করুন।

Node-এ text stream করতে:

```ts
const stream = await run(agent, "Write a haiku about merge conflicts.", { stream: true });
stream.toTextStream({ compatibleWithNodeStreams: true }).pipe(process.stdout);
await stream.completed;
```

Tracing বন্ধ করা যায় ওপরের মতো `setTracingDisabled(true)` দিয়ে, অথবা `OPENAI_AGENTS_DISABLE_TRACING=1` দিয়ে। এই code চালান server-এ বা CLI-তে, browser bundle-এ নয়। Tokens CORS header পাঠায় না, আর যে-ই dev tools খুলবে সে-ই আপনার key দেখে ফেলবে।

## ঠিকমতো চলছে কিনা দেখুন

`python agent.py` চালান। Terminal-এ ছোট একটা উত্তর ছাপা হলে বুঝবেন key, base URL আর model ID ঠিক আছে। এরপর [Dashboard](/dashboard)-এ Usage analytics খুলে request-টা খুঁজুন। Call ফেল করলে আগে [cURL](/docs/curl) দিয়ে endpoint test করুন। সেখানে `200` আসছে অথচ agent-এ ফেল করছে, তাহলে সমস্যা SDK setup-এ, key-তে নয়।

## Model বাছাই

Agent ঘুরতে থাকে: tool ডাকে, result পড়ে, আবার ডাকে। তাই model-কে tool call ভালো সামলাতে হবে আর লম্বা context ধরে রাখতে হবে। কিছু model সাধারণ chat-এ ঠিক উত্তর দেয়, কিন্তু tool-এ ফেল করে। কোন model agent-এর কাজে মানায়, তা [Choosing a model](/docs/choosing-a-model)-এ আছে, আর [/models](/models)-এ প্রতিটা model-এর পেজে দেখা যায় তার context window কত আর tool সাপোর্ট করে কিনা। প্রতিটা উত্তরের দৈর্ঘ্যে সীমা দিতে চাইলে `ModelSettings`-এর মধ্য দিয়ে `max_tokens` সেট করুন। কয়েক রাউন্ড tool চললে অনেক token যেতে পারে, তাই agent-কে যে key দেবেন তাতে spend cap বসিয়ে দিন ([API keys](/docs/api-keys))।

## সীমাবদ্ধতা আর যা চলে না

- **শুধু Responses-এ চলে এমন feature।** Hosted tool (web search, file search, code interpreter), `previous_response_id` আর Responses-only বাকি field Chat Completions পথে পাওয়া যায় না। Strict validation চালু না করলে SDK ওই field-গুলো চুপচাপ বাদ দিয়ে দেয় (`OpenAIProvider`-এ `strict_feature_validation=True`, `MultiProvider`-এ `openai_strict_feature_validation=True`)।
- **Structured output।** SDK `json_schema` response format পাঠায়। Tokens ID-র পেছনের model সেটা সাপোর্ট না করলে upstream request ফিরিয়ে দেয় `400` (`invalid_request`) দিয়ে। Structured output সাপোর্ট করে এমন model নিন ([Structured output](/docs/structured-output))।
- **Audio আর Realtime।** Audio output চাইলে Chat Completions adapter `AgentsException("Audio is not currently supported")` ছোঁড়ে। Realtime আর voice agent-এর জন্য OpenAI-র নিজের endpoint লাগে, সেগুলো Tokens দিয়ে চলে না।
- **Tracing।** Trace যায় OpenAI-তে, Tokens-এ নয়, আর Tokens key দিয়ে সেগুলো upload করা যায় না।
- **`finish_reason="length"`-এ খালি উত্তর।** Model যদি কিছু output না দিয়েই length limit-এ থেমে যায়, adapter `ModelBehaviorError` ছোঁড়ে। এটা token বা reasoning budget-এর সমস্যা। `max_tokens` বাড়ান, নয়তো এমন model নিন যার লুকানো reasoning কম।

## সমস্যা হলে

**`UserError: Unknown prefix: <first part of your model id>`।** Model-টা agent-কে string হিসেবে দেওয়া হয়েছে, আর SDK-র default provider slash-এর আগের অংশটাকে provider prefix ধরে নিয়েছে। `OpenAIChatCompletionsModel` object দিন, ওপরের `ModelProvider` ব্যবহার করুন, নয়তো `MultiProvider`-এ `unknown_prefix_mode="model_id"` দিন।

**404 `model_not_found`।** হয় ID-তে বানান ভুল, নয়তো SDK শুরুর `openai/` কেটে দিয়েছে। Tokens usage log-এর ID-র সাথে আপনি যেটা পাঠাতে চেয়েছিলেন সেটা মিলিয়ে দেখুন, আর `GET https://tokens.bd/v1/models`-এর সাথেও যাচাই করুন।

**`/v1/responses` থেকে `404` বা `400`।** SDK এখনও Responses API-তেই আছে। `OpenAIChatCompletionsModel` ব্যবহার করুন, অথবা `set_default_openai_api("chat_completions")` দিন।

**`api.openai.com` থেকে `401` error, বা log-এ "incorrect API key", অথচ agent উত্তর দিচ্ছে।** এগুলো trace upload-এর error। Tracing বন্ধ করুন।

**Tokens থেকে 401 `invalid_api_key`।** `TOKENS_API_KEY`-এর key ভুল, নয়তো revoke করা। [/dashboard/keys](/dashboard/keys)-এ গিয়ে নতুন একটা বানান।

**402 `insufficient_credits`, 403 `model_not_allowed_on_key`, 429 `window_exhausted`।** এগুলো অ্যাকাউন্টের সীমার ব্যাপার, SDK-র সমস্যা নয়। দেখুন [Errors](/docs/errors) আর [Troubleshooting](/docs/troubleshooting)। Agent একসাথে অনেক request ছুড়লে `429 concurrency_limit` লাগতে পারে। তখন parallelism কমান ([Rate limits](/docs/rate-limits))।

**Error আসে SDK exception হয়ে।** SDK OpenAI client-কে মুড়ে রাখে, তাই Tokens-এর error আসে `openai` exception হিসেবে। `e.code` আর `e.response.headers.get("x-tokens-request-id")` পড়ুন, আর [support](/docs/support)-এর সাথে যোগাযোগের সময় request id-টা দিয়ে দিন।

---
Page: https://tokens.bd/bn/docs/openai-agents-sdk
