Agent workflows · 2026-10-14
Free Qwen for AI agents: tool calling with Qwen3.8 27B
An agent loop on Qwen3.8 27B, free until 2 November 2026, whose model card lists tool calling: a two-turn OpenAI SDK loop, max_tokens, 429, 402 and 410.
Short answer: free until 2 November 2026, 00:00 (TRT)
You can call Qwen3.8 27B for free until 2 November 2026, 00:00 (TRT), and its model card lists tool/function calling, so you can build an agent loop on this row and try it with your own tools. LLMTR (llmtr.com) is a gateway that gives access to language models hosted in Türkiye and at global providers through one OpenAI-compatible API. The model id is heabsy/qwen3.8-27b-heabsy-free and the base URL is https://llmtr.com/v1. Until that date the price is $0.00 per 1M input tokens and $0.00 per 1M output tokens, and no credit is deducted.
Use is limited per account per day. The model card also lists image input, and the context window is 262,144 tokens. This guide builds a two-turn tool loop with the OpenAI Python SDK, covers the settings that matter inside an agent loop, and shows how the loop should react to responses such as 429, 402 and 410.
How do you build a tool-calling agent with a free Qwen?
The core of an agent is two requests. In the first, you send the conversation and the definitions of the tools the model may use. If the model decides to call a tool, message.tool_calls in the response is filled in; each call carries the tool name and its arguments as JSON. You run the tool in your own code, append the assistant message that holds the tool call and a tool message with the result, and send the second request. This time the model writes the final answer from the tool result.
The example below has one tool, get_weather(city). Instead of a real weather service, a local stub returns a fixed result; to connect your own tool, you replace only that function. The tool_call_id in the tool message must match the call id the model returned; that is how the model knows which result belongs to which call. max_tokens is 4096 because reasoning tokens count toward that limit too.
In an existing OpenAI client, three things change: base_url becomes https://llmtr.com/v1, api_key takes your LLMTR key, and the model string becomes heabsy/qwen3.8-27b-heabsy-free. The SDK sends the key in the Authorization: Bearer header for you.
Two-turn loop with the OpenAI Python SDK: it defines the get_weather tool, answers a tool call, if the model makes one, with a local function and prints the final answer from the second request.
import json
from openai import OpenAI
client = OpenAI(base_url="https://llmtr.com/v1", api_key="llmtr-your_key")
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
},
}]
def get_weather(city):
# Local stub: replace it with a real weather lookup.
return {"city": city, "temperature_c": 18, "condition": "light rain"}
messages = [{"role": "user", "content": "Do I need an umbrella in Istanbul today?"}]
# Turn 1: the model decides whether to call a tool.
first = client.chat.completions.create(
model="heabsy/qwen3.8-27b-heabsy-free",
max_tokens=4096,
tools=tools,
messages=messages,
)
message = first.choices[0].message
if message.tool_calls:
# Keep the assistant turn that asked for the tools in the history.
messages.append({
"role": "assistant",
"content": message.content,
"tool_calls": [call.model_dump() for call in message.tool_calls],
})
for call in message.tool_calls:
args = json.loads(call.function.arguments)
result = get_weather(args["city"])
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps(result),
})
# Turn 2: the model answers from the tool result.
second = client.chat.completions.create(
model="heabsy/qwen3.8-27b-heabsy-free",
max_tokens=4096,
tools=tools,
messages=messages,
)
print(second.choices[0].message.content)
else:
print(message.content)
Settings that matter in an agent loop
The context window is 262,144 tokens; long tool outputs and the growing message history have to fit inside it. max_tokens cannot exceed 32,768; a larger value is refused with HTTP 400 invalid_request. Reasoning is on by default and those tokens count toward max_tokens, so leave the model room on turns where it picks a tool: 4096 or more is a good start. If a response comes back with finish_reason: "length", raise max_tokens and send the request again.
reasoning_effort is not supported on this model; a request that sends it is refused with HTTP 400 invalid_request, so turn it off if your library or framework adds it on its own. stream: true is accepted, but the answer arrives in chunks after it completes; set how long your client waits for the first chunk accordingly. The model is called only through /v1/chat/completions; /v1/responses is not available.
| Setting | Value |
|---|---|
| Model id | heabsy/qwen3.8-27b-heabsy-free |
| Price (until 2 November 2026, 00:00 TRT) | $0.00 input / $0.00 output per 1M tokens |
| Context window | 262,144 tokens |
| max_tokens limit | 32,768; larger values get HTTP 400 invalid_request |
| Reasoning | on by default; counts toward max_tokens, use 4096 or more on tool turns |
| reasoning_effort | not supported; HTTP 400 invalid_request |
| Tool/function calling | listed on the model card |
| Image input | listed on the model card |
| Streaming (stream: true) | accepted; the answer arrives in chunks after it completes |
| Endpoint | /v1/chat/completions; /v1/responses not available |
Hardening the loop
Do not assume how many tool calls a turn will hold. tool_calls can be empty, hold one call or hold several; your code should handle all three and append a separate tool message for each call. If it is empty, the model's reply is the final answer. Parse the arguments as JSON and check that the fields you expect are there before you run anything; when the arguments do not parse, you can send the error back to the model as the tool message instead of running the tool.
Cap the number of turns. As long as the model keeps calling tools, the loop keeps going; stop after, say, five or ten turns and return what you have. The cap prevents an endless loop and keeps a single task from using up the daily allowance.
HTTP 429 means one of the free-use limits has been reached; that limit can be daily or per minute, and the response carries a Retry-After header. The limit frees up on its own, so your client should wait for the time in that header and then retry. On an account that has not topped up yet, a request can return HTTP 402 after some use, with details.reason set to account_verification_required. Automated-use protection is asking for a one-time account verification: top up once from Dashboard > Billing and retry after a minute; the model is not charged to your balance. HTTP 410 model_retired is permanent: retrying does not help, so stop the loop and change the model string.
Using it from agent frameworks
Any framework that accepts an OpenAI-compatible base_url, an api_key and a model string connects the same way: https://llmtr.com/v1 as base_url, your LLMTR key as api_key and heabsy/qwen3.8-27b-heabsy-free as the model. For example, a framework's OpenAI-compatible chat client takes these three values; tool definitions and the loop run through the framework's own mechanism, and requests still go to /v1/chat/completions.
If the framework sends reasoning_effort, turn it off; if a client uses the Responses API, switch it to Chat Completions mode. Before production, try it with your own tools: tool calling is a feature the model card lists, so run an end-to-end scenario with your own tool schemas and prompt sizes and look at what the model returns.
Before you start and after 2 November
Heabsy models cannot be called until your account has granted the data-transfer consent for Heabsy; without it every request returns HTTP 403 provider_consent_required. You grant it from the Data-transfer consents card in Settings; consent is account-level and applies to every API key on the account. According to Heabsy, the model runs in EU/EEA data centres, and prompts and completions are not stored or used for training.
The free period ends on 2 November 2026, 00:00 (TRT), which is Europe/Istanbul time, UTC+3. After that, requests to heabsy/qwen3.8-27b-heabsy-free return HTTP 410 model_retired, and the error names the metered heabsy/qwen3.8-27b-heabsy. Changing the model string to that id is all your agent needs; the tool definitions and the loop stay the same. The metered id is billed from prepaid credit per 1M tokens at $0.40 input, $0.05 cached input and $3.00 output.
Build a tool-calling agent with the free Qwen3.8 27B
Grant the Heabsy consent, create an API key, define your tools and run the two-turn loop with heabsy/qwen3.8-27b-heabsy-free before 2 November 2026, 00:00 (TRT).
- Consent and key. At llmtr.com, grant the Heabsy data-transfer consent in Settings, create a key under Dashboard > API Keys and store it in the LLMTR_API_KEY environment variable.
- Define tools. Write each tool as an OpenAI function definition with a name, a description and its parameters as a JSON schema, and implement the tool as a function in your own code.
- Run the loop. Send the first request with tools; if tool_calls come back, run the tool, append the result as a tool message with its tool_call_id and get the final answer from the second request. On 429, wait for Retry-After; on 410, stop.
Frequently asked questions
Is running an agent on Qwen3.8 27B really free?
Yes. heabsy/qwen3.8-27b-heabsy-free costs $0.00 per 1M input and output tokens until 2 November 2026, 00:00 (TRT), and no credit is deducted. Use is limited per account per day; at the limit the API returns HTTP 429 with a Retry-After header.
Does the free Qwen support tool calling?
The model card lists tool/function calling. You send the tools field in OpenAI format, and the model returns its calls in message.tool_calls. Before production, try it with your own tools.
What happens to my agent after 2 November 2026?
Requests return HTTP 410 model_retired, and the error names the metered heabsy/qwen3.8-27b-heabsy. Once you change the model string, the same agent keeps working at $0.40 input and $3.00 output per 1M tokens.