Skip to content

CrewAI

Tokens-এ CrewAI-র agent আর crew চালান: custom base URL আর custom_openai-সহ LLM class, model ID কীভাবে লিখবেন, streaming, tool call, rate limit আর troubleshooting।

যেসব tool-এ কাজ করেCrewAI
Markdown-এ দেখুন
এই পাতায়

CrewAI একটা Python framework, যেখানে agent-রা একটা crew হয়ে একসাথে কাজ করে। প্রতিটা agent একটা LLM পায়, আর CrewAI সেই LLM-এর request যেকোনো OpenAI-compatible endpoint-এ পাঠাতে পারে। Tokens তেমনই একটা: CrewAI আপনার Tokens key দিয়ে OpenAI Chat Completions request পাঠায় https://tokens.bd/v1-এ।

যে জায়গাটায় সবাই আটকায় সেটা হলো model string। Tokens-এর model ID-র মধ্যে আগে থেকেই একটা slash থাকে (provider/model), আর CrewAI প্রথম slash-এর আগের অংশটাও পড়ে। কী লিখতে হবে তা পরের section-এ দেখানো হয়েছে।

কী কী যাচাই করা হয়েছে

এই পেজ লেখা হয়েছে CrewAI-র LLMs documentation (docs.crewai.com, 2026 সালের অক্টোবরে দেখা) আর PyPI ও GitHub-এ থাকা crewai 1.15.27-এর source দেখে (release হয়েছে 9 অক্টোবর 2026-এ)। নিচের routing-এর নিয়মগুলো এসেছে ওই source-এর llm.py থেকে, কারণ documentation-এর পেজে সেগুলো লেখা নেই। Code-টা documentation আর source দেখে মেলানো হয়েছে, Tokens-এর বিরুদ্ধে শুরু থেকে শেষ পর্যন্ত চালিয়ে দেখা হয়নি।

যা যা লাগবে#

  • API keys থেকে নেওয়া একটা Tokens key, TOKENS_API_KEY নামে export করা।
  • /models থেকে একটা model ID। আপনার agent tool ব্যবহার করলে এমন model নিন যা tool calling সাপোর্ট করে (Choosing a model)।
  • Python 3.10 থেকে 3.13 (CrewAI 1.15.27 লিখেছে >=3.10,<3.14)।
bash
pip install crewai
export TOKENS_API_KEY="tok_live_your_key"

CrewAI-র docs uv দিয়ে install করতে বলে (command line tool-এর জন্য uv tool install crewai, project-এর ভেতরে uv add crewai)। সাধারণ script-এর জন্য pip-ও একইভাবে চলে। crewai আগে থেকেই openai package-এর ওপর নির্ভর করে, তাই এই setup-এ litellm extra লাগে না।

LLM সাজান#

llm.py
import os
from crewai import LLM

llm = LLM(
    model="deepseek/deepseek-v4.1-flash",
    base_url="https://tokens.bd/v1",
    api_key=os.environ["TOKENS_API_KEY"],
    custom_openai=True,
    timeout=120,
    max_retries=2,
)

প্রতিটা অংশ কী করে:

Settingকেন
modelTokens-এর model ID, /models-এ যেভাবে লেখা আছে ঠিক সেভাবে।
base_urlhttps://tokens.bd/v1, /v1-সহ। CrewAI এটা OpenAI Python SDK-কে দিয়ে দেয়, আর SDK শেষে /chat/completions জুড়ে নেয়।
custom_openai=TrueModel string দেখতে যেমনই হোক, এই LLM-এর জন্য CrewAI-কে তার নিজস্ব native OpenAI client ব্যবহার করতে বাধ্য করে। CrewAI-র নিজের gateway উদাহরণেও এটা আছে। এর সাথে custom endpoint-ও লাগে, তাই base_url দিতে ভুলে গেলে error আসে।
timeout, max_retriesResponse-এর জন্য কত সেকেন্ড অপেক্ষা করবে আর কতবার retry করবে। CrewAI-র docs-এ দুটোই আছে। না দিলে OpenAI SDK-র default খাটে (10 মিনিট, 2 বার retry)।

Model ID কীভাবে লিখবেন#

custom_openai=True থাকলে Tokens-এর ID ঠিক catalog-এ যেমন আছে তেমনই লিখুন, আগে বাড়তি কোনো prefix ছাড়া। CrewAI শুরুর openai/ থাকলে সেটা কেটে নেয়, বাকিটা না বদলে পাঠায়। তাই deepseek/deepseek-v4.1-flash Tokens-এ পৌঁছায় deepseek/deepseek-v4.1-flash হিসেবেই।

দুটো ক্ষেত্রে সাবধান থাকুন:

  • custom_openai=True বাদ দেবেন না। এটা না থাকলে CrewAI প্রথম slash-এর আগের অংশটাকে provider-এর নাম ধরে। Tokens-এর কোনো ID এমন নামে শুরু হতে পারে যা CrewAI নিজের provider বলে চেনে (deepseek/ তার একটা), আর তখন request Tokens-এ না গিয়ে সেই provider-এর client-এ চলে যায়। LiteLLM-এর ধরনে model="openai/<tokens id>" আর base_url দিলেও OpenAI client-এ পৌঁছানো যায়, কিন্তু custom_openai=True দিলে আন্দাজের কিছু থাকে না।
  • যে ID নিজেই openai/ দিয়ে শুরু। শুরুর openai/ কেটে ফেলা হয়। Tokens-এর কোনো ID যদি নিজেই openai/ দিয়ে শুরু হয়, তাহলে দুবার লিখুন: model="openai/openai/<name>"।

CrewAI-র LLMs পেজ বলে সবসময় provider prefix দিতে। Tokens-এর ID তো আগে থেকেই provider/model, তাই সেই নিয়ম মেটানো আছে। CrewAI-র নিজের custom-endpoint উদাহরণেও gateway-র ID এভাবেই দেওয়া হয়।

বদলে environment variable ব্যবহার করুন#

CrewAI OPENAI_BASE_URL আর OPENAI_API_KEY-ও পড়ে (এর docs-এ দুটোই আছে):

bash
export OPENAI_BASE_URL="https://tokens.bd/v1"
export OPENAI_API_KEY="$TOKENS_API_KEY"
python
from crewai import LLM

llm = LLM(model="deepseek/deepseek-v4.1-flash", custom_openai=True)

এই variable-গুলো পুরো shell জুড়ে খাটে। একই shell-এ OpenAI-ভিত্তিক অন্য যে tool-ই চলুক, তার traffic-ও Tokens-এ যাবে। base_url আর api_key code-এ দিলে বদলটা শুধু CrewAI-তেই সীমিত থাকে।

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

আগে agent ছাড়া শুধু LLM-টাকেই call করে দেখুন:

check.py
from llm import llm

print(llm.call("Reply with the single word: ready"))

স্বাভাবিক একটা বাক্য ফেরত এলে বুঝবেন key, base URL আর model ID, তিনটেই ঠিক। Token খরচ না করে ID যাচাই করতে চাইলে catalog-টা list করুন:

bash
curl -s https://tokens.bd/v1/models -H "Authorization: Bearer $TOKENS_API_KEY"

ছোট্ট একটা crew#

crew.py
from crewai import Agent, Crew, Task
from llm import llm

reviewer = Agent(
    role="Python code reviewer",
    goal="Point out bugs and unclear names in short snippets",
    backstory="You review pull requests for a small team and keep feedback short.",
    llm=llm,
    max_iter=5,
)

task = Task(
    description="Review this function and list the problems:\n\ndef avg(xs): return sum(xs)/len(xs)",
    expected_output="A bullet list with at most three items.",
    agent=reviewer,
)

crew = Crew(agents=[reviewer], tasks=[task])
result = crew.kickoff()

print(result.raw)
print(crew.usage_metrics)

result.raw হলো চূড়ান্ত text। crew.usage_metrics ওই run-এর token count দেখায়। তবে Tokens-এ আপনার বিল কত হলো তা দেখবেন Dashboard-এর usage পেজ থেকে, CrewAI-র সংখ্যা থেকে নয়।

max_iter ঠিক করে একটা agent উত্তর দেওয়ার আগে সর্বোচ্চ কয়টা reasoning ধাপ নিতে পারবে (CrewAI-র default 20)। প্রতিটা ধাপ মানে একটা request, আর Tokens সেটার বিল করে। তাই test করার সময় কম cap দিলে খরচও কম হয়।

Response stream করুন#

LLM-এ stream=True দিন:

python
streaming_llm = LLM(
    model="deepseek/deepseek-v4.1-flash",
    base_url="https://tokens.bd/v1",
    api_key=os.environ["TOKENS_API_KEY"],
    custom_openai=True,
    stream=True,
)

CrewAI প্রতিটা chunk-এর জন্য একটা LLMStreamChunkEvent ছাড়ে। নিচের listener-টা CrewAI-র LLMs পেজের উদাহরণ:

python
from crewai.events import BaseEventListener, LLMStreamChunkEvent

class MyCustomListener(BaseEventListener):
    def setup_listeners(self, crewai_event_bus):
        @crewai_event_bus.on(LLMStreamChunkEvent)
        def on_llm_stream_chunk(self, event: LLMStreamChunkEvent):
            print(f"Received chunk: {event.chunk}")

my_listener = MyCustomListener()

Crew চালানোর আগেই listener-টা বানিয়ে নিন। Streaming চালু থাকলে CrewAI Tokens-এর কাছে stream_options.include_usage চায়, তাই usage-এর সংখ্যাও আসে। Wire format-এর জন্য Streaming দেখুন।

Tool call#

crewai.tools-এর @tool আর tools argument দিয়ে agent-কে tool দিন:

python
from crewai import Agent
from crewai.tools import tool
from llm import llm

@tool("Get weather")
def get_weather(city: str) -> str:
    """Current weather for a city. Use it when the user asks about the weather."""
    return f"{city}: light rain, 29C"

agent = Agent(
    role="Travel helper",
    goal="Answer weather questions for travellers",
    backstory="You know Bangladesh well.",
    llm=llm,
    tools=[get_weather],
)

Custom endpoint-এর জন্য function calling-এর আলাদা কোনো switch নেই। CrewAI-র source-এ OpenAI provider-এর supports_function_calling() সবসময় true ফেরত দেয়, শুধু o1-ধরনের model হলে দেয় না। তাই CrewAI tool পাঠায় OpenAI-র format-এ। Model সেগুলো ঠিকমতো ডাকবে কি না, সেটা নির্ভর করে model-এর ওপর: /models-এ তার পেজ দেখুন আর পড়ুন Tool calling। কোনো model tool এড়িয়ে গেলে code বদলানোর আগে অন্য model চেষ্টা করুন।

সীমা আর যা খেয়াল রাখবেন#

  • প্রতি মিনিটের request। একাধিক agent-এর crew অল্প সময়ে অনেক request ছুড়তে পারে। আপনার plan-এর সীমার নিচে থাকতে Agent-এ max_rpm দিন (CrewAI-র docs-এ এটাকে প্রতি মিনিটের request-এর cap বলা হয়েছে)। সীমা পেরোলে 429 rate_limited আসে। দেখুন Rate limits।
  • Parallel task। একসাথে চলা task-গুলো আপনার অ্যাকাউন্টের concurrent request-এর সীমার হিসাবে পড়ে আর 429 concurrency_limit ফেরত আসতে পারে। Task-গুলো পরপর চালান, নয়তো parallelism কমান।
  • লম্বা generation। Gateway একটা response-এর জন্য 600 সেকেন্ড পর্যন্ত অপেক্ষা করে। CrewAI-র timeout এর সমান বা কম রাখুন, আর খুব লম্বা output হলে stream=True দিন।
  • যা এখানে ধরা হয়নি। CrewAI-র যে feature নিজে থেকে embeddings model ডাকে (memory, knowledge source), সেগুলো এই পেজে সাজানো হয়নি। Tokens embeddings চালায় (Embeddings), কিন্তু ওই feature-গুলোকে একই endpoint-এ দেখিয়ে দেওয়ার কাজটা আপনাকেই করতে হবে।

সমস্যা হলে#

লক্ষণকারণ ও সমাধান
ImportError: Unable to initialize LLM ... LiteLLM fallback package is not installedCrewAI তার OpenAI client বেছে নেয়নি, LiteLLM-এ fallback করেছে। custom_openai=True আর base_url দিন। crewai[litellm] install করলেও error থামে, কিন্তু তখন routing করে LiteLLM।
Error message-এ অন্য কোনো provider-এর API key-এর কথাModel string CrewAI-র নিজের কোনো provider-এর সাথে মিলে গেছে। custom_openai=True দিন।
401 missing_api_key বা invalid_api_keyKey request-এ পৌঁছায়নি। api_key= সরাসরি দিন, আর crew যে process-এ চলছে সেখানে TOKENS_API_KEY set আছে কি না দেখুন। দেখুন API keys।
404 model_not_foundID ভুল, অথবা ID-র নিজের openai/ অংশটা CrewAI কেটে দিয়েছে। /models থেকে ID copy করুন; যে ID openai/ দিয়ে শুরু, তাতে prefix-টা দুবার লিখুন।
402 insufficient_creditsPlan-এর credit আর Wallet মিলিয়েও request-এর খরচ কুলোচ্ছে না। Billing-এ টাকা যোগ করুন। max_iter ধাপ পর্যন্ত চলা loop-এ credit দ্রুত শেষ হয়।
429 rate_limited বা concurrency_limitRequest বেশি হয়ে গেছে। max_rpm দিন, task পরপর চালান, Retry-After-এ বলা সেকেন্ড অপেক্ষা করুন। window_exhausted মানে plan-এর একটা window শেষ, তাই reset না হওয়া পর্যন্ত retry করে লাভ নেই।
TimeoutLLM-এ timeout বাড়ান, অথবা stream করুন। 504 upstream_timeout আসে upstream থেকে, 600 সেকেন্ড পর। request ছোট করে দেখুন।

সব code-এর তালিকা Errors পেজে। Support-এর কাছে সাহায্য চাইলে x-tokens-request-id response header-টা সাথে দিন। এই পেজের উদাহরণগুলো response header দেখায় না, তাই ওটা পেতে call-টা একবার cURL আর -i দিয়ে চালিয়ে নিন।

এই পাতাটা কি কাজে লেগেছে?

এখনো আটকে আছেন? Support ticket খুলুন

আপনার agent set up করতে সাহায্য লাগবে?

Connection tester দিয়ে সংযোগ পরীক্ষা করে নিন, অথবা একটা API key তৈরি করুন।