The core of an agent: reasoning plus tools, using Grok 4.6 and open models as examples
A model with reasoning and function calling is a convenient foundation for an agent. We build a minimal tool-calling loop on the Yenisei base_url and pick a model for it.
Yenisei team
The core of an agent: reasoning plus tools, using Grok 4.6 and open models as examples
An agent is a model that decides in a loop what to do next, calls tools and takes their results into account. For this to work, the model needs two things at once: careful reasoning and reliable function calling. Grok 4.6 from xAI is often cited as an example of that combination.
Grok is not in the Yenisei catalog, but the same combination is available in open models: Kimi K2 Thinking (kimi-k2-thinking), DeepSeek V4 Pro (deepseek-pro), GLM 5.3 (glm-5.3). We will build the loop on them.
Why reasoning matters here
The weak spot of many agents is choosing which tool to call and when. A model without proper reasoning grabs the first call that comes to mind, gets stuck in a loop, or abandons the task halfway. A reasoning model first sketches a plan, then acts, and the loop converges faster.
A minimal tool-calling loop
We define a tool using the OpenAI-compatible schema and hand it to the model:
from openai import OpenAIimport jsonclient = OpenAI(base_url="https://api.yenisei.ru/v1", api_key="YENISEI_KEY")MODEL = "kimi-k2-thinking"tools = [{ "type": "function", "function": { "name": "get_order_status", "description": "Return the status of an order by its number", "parameters": { "type": "object", "properties": {"order_id": {"type": "string"}}, "required": ["order_id"], }, },}]messages = [{"role": "user", "content": "What is going on with my order A-4417?"}]resp = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)msg = resp.choices[0].messageif msg.tool_calls: call = msg.tool_calls[0] args = json.loads(call.function.arguments) result = lookup_order(args["order_id"]) # your function messages.append(msg) messages.append({ "role": "tool", "tool_call_id": call.id, "content": json.dumps(result, ensure_ascii=False), }) final = client.chat.completions.create(model=MODEL, messages=messages, tools=tools) print(final.choices[0].message.content)What is easy to break
- Too many tools at once. Give the model 30 functions and it will start getting confused. Keep the set minimal and group similar things.
- Vague descriptions.
descriptionis part of the prompt. "Get data" is bad; "Return the status of an order by its number" is good. - No loop limit. Always cap the number of iterations, otherwise on a rare edge case the agent can spin forever and burn your budget.
- Ignoring tool errors. If a function returned an error, put its text into
role: tool; a good model will usually propose a workaround on its own.
Which model to take
- Kimi K2 Thinking shows its reasoning and calls functions confidently; a good choice for an agent with branching.
- DeepSeek V4 Pro has reasoning, tools and a context of up to a million tokens: a long call history fits in the window in full.
- GLM 5.3 is strong on multi-step agent scenarios, and its window is also very long.
If the agent is essentially linear ("took a request, called one API, returned an answer"), a reasoning flagship is excessive. Such a loop is cheaper to build on DeepSeek V4 Flash (deepseek-flash) or GLM 5.3 Flash (glm-5.3-flash) without paying for deliberation where the choice is obvious.
Long context here is also insurance: the dialogue history with the results of all calls fits in the window, and the agent does not have to "forget" its first steps in the middle of a task.