Knowledge baseSeptember 3, 2026·updated September 3, 2026

Development of AI agents: cycle, tools, memory, control

What the agent is physically assembled from: a call cycle, tool diagrams, three layers of memory and limiters, without which it goes into disarray.

What does this solve?

Development AI-agents begins where the chat stops helping: the data is in the database, the action is performed in someone else’s API, and the result must be checked and recorded. In correspondence with the model, a person works as a transmission bus - unloaded, inserted, took the answer, applied it with his hands. The agent completes the circle itself: it goes for data, calls the operation, repeats the step after an error, and stops when the task is closed. The board is a new engineering job: describe the tools, install limiters, learn to read the step log.

How it works

The agent is assembled from four parts: cycle, tools, memory, control. Remove any of them and you'll end up with either a chatty chat or an uncontrollable script.

Cycle

The kernel lives in the orchestrator code and looks like a regular one while:

  1. Collect a request: system instructions, history, new input, description of available tools.
  2. Send to model.
  3. Parse the answer. The model will return either the final text or a structured call request - tool_calls with function name and arguments in JSON.
  4. The orchestrator executes the call with its code and puts the result back into history as a separate message with the role tool.
  5. Return to step 2 - until the final text arrives or until the limiter is triggered.

The model does not perform anything itself. It returns JSON with the function name and arguments, everything else is done by the code that received this JSON. Hence the main lever: the set of tools included in the request is a complete list of what the agent is physically capable of doing.

Tools

Each instrument is described by three fields: name, description, parameters (JSON Schema). The model selects according to the description, so the description is written for the reader, who sees nothing except it: what it does, when to use it, what it doesn’t do, what it will return.

Rules that save days of debugging later:

  • One action - one tool. Universal do_everything with field action inside turns choosing into guessing.
  • There are a minimum of required parameters, the rest have default values. Each required field increases the chance that the model will come up with its content.
  • Structured answer: status, data, and error text that can be used to correct it. Ошибка 500 cannot be treated, период задан наоборот: date_from позже date_to —is treated in the next step.
  • Reading and writing are separated at the name level: get_orders i create_order never live in the same function.
  • Pagination and limits are inside the tool, not in the head of the model. A tool that can return tens of thousands of rows will kill the context on the first call.

Second way - MCP: the tool is described once on the server side and connects to any compatible client without rewriting adapters for each runtime.

Memory

Long history and memory are two different things. Three layers.

LayerWhere does he live?What hitsWhen to clean
Step contextmodel windowsystem instructions, latest messages, call resultswhen overflowing, displacing the old one
Working memoryfile or task tableplan, what has already been done, intermediate conclusionson task completion
Long-termDB, vector index, notes repositorydomain rules, facts, past decisionsmanual, revision

A typical mistake is to drag the entire correspondence into each step. The context becomes clogged with raw uploads, the model begins to respond at the beginning of the dialogue and loses fresh facts. Working method: save the result of a difficult call to a file, put a short summary and path to the file in the history, and read the file itself with the tool on demand.

Long-term memory is valuable not because of its volume, but because of the rules it contains. The resolved glitch ends with a line in the agent's instructions, otherwise the same glitch will happen again next week.

Control

Limiters are placed in the orchestrator code, not in the prompt. Prompt is a recommendation, code is a boundary.

  • White list of tools per role or per launch.
  • Human confirmation for everything that writes outside.
  • max_steps and timeout for the task. Without them, looping eats up the budget silently.
  • Token budget with stop when reached.
  • Sandbox for executing code and commands.
  • Log: step number, tool name, arguments, truncated result, duration, cost.
  • Idempotency of record: operation key so that replay after timeout does not create a duplicate.

Rule: the model only proposes a call, executes its code, and the right to write is issued by a list, not a trust.

How to connect

Step 1. Select one task with a test result. “Help with analytics” is not checked. “By the name of the company, find its contracts and return the end dates” - tested using a dozen examples.

Step 2. Describe the tools. Start with two or three, reading only. The diagram looks like this:

{
  "type": "function",
  "function": {
    "name": "get_orders",
    "description": "Вернуть заказы клиента за период. Только чтение. Максимум 200 строк, дальше — cursor.",
    "parameters": {
      "type": "object",
      "properties": {
        "client_id": {"type": "integer"},
        "date_from": {"type": "string", "format": "date"},
        "date_to": {"type": "string", "format": "date"},
        "cursor": {"type": "string"}
      },
      "required": ["client_id"]
    }
  }
}

Step 3. Write a cycle. The framework is the same in any language:

messages = [{"role": "system", "content": SYSTEM}, {"role": "user", "content": task}]
for step in range(MAX_STEPS):
    resp = client.chat(messages=messages, tools=TOOLS)
    msg = resp.choices[0].message
    messages.append(msg)
    if not msg.tool_calls:
        return msg.content
    for call in msg.tool_calls:
        result = registry[call.function.name](json.loads(call.function.arguments))
        log(step, call.function.name, call.function.arguments, result)
        messages.append({"role": "tool", "tool_call_id": call.id,
                         "content": json.dumps(result, ensure_ascii=False)[:MAX_TOOL_CHARS]})
raise StepLimit()

Cutting result (MAX_TOOL_CHARS) is required from the first day, otherwise one unsuccessful call will close the window.

Step 4. System instructions. Four blocks: role and subject area; what is forbidden (what tools not to touch, what not to invent); final answer format; completion criterion - by what criteria the task is considered closed.

Step 5. Log from the first launch. Write to a file or table, not stdout. Analysis of any strange behavior begins with reading the sequence of calls, and without it, fortune telling is left.

Step 6. Limiters. MAX_STEPS, timeout for tool, timeout for task, limit of total tokens, allowlist.

Step 7. Gold set. Several dozen real inputs with a known correct outcome, folded into a file. Running the set is the only way to see that editing the prompt improved the behavior and did not rearrange the errors.

Step 8. Write permissions. Added last, one operation at a time, with confirmation and with an idempotency key.

Useful scripts

  • Parsing incoming mail: classify the letter, pull out the details, create a card in the tracker.
  • Monitoring duty: collect errors overnight, group them by reason, send a summary with links.
  • Data reconciliation between two systems: find discrepancies and return a list of pairs with an explanation, without recording.
  • Preparation of a regular report: go to the database and advertising office, collect numbers, prepare according to a template.
  • First line of support: find the answer in the knowledge base, respond, escalate when unsure.
  • Routine in the tracker: transfer tasks according to the rules, add tags, collect a list of stuck ones.

Limitations

A problem with one deterministic answer is solved cheaper by a script: if the rule is written in SQL or twenty lines of code, the agent will only add non-determinism and a token bill.

Hard latency is poorly compatible with the loop: each step is a network call to the model plus execution of the tool, and the number of steps is unknown in advance.

Debugging is different from usual: the same input gives different trajectories. Tests are written for the outcome and invariants (no more than N steps, not a single call from the blacklist, the answer scheme is valid), and not for the exact text.

The cost grows non-linearly: each step anew runs through the entire accumulated history, so a long chain becomes more expensive faster than it seems from the number of steps.

Responsibility is not delegated. Everything that the agent does outwardly - letters, payments, publications, deletions - remains with the owner of the process, and this dictates where the acknowledgment stands.

How to check the result

Run the gold set and look at the five numbers from the magazine:

  1. The percentage of problems that reach the final answer without exhausting the step limit.
  2. Proportion of correct outcomes during manual comparison with the standard.
  3. Average and maximum number of steps. A spike in the maximum is a sign of cycling.
  4. Proportion of calls rejected by schema validation. High—the description of the parameters is ambiguous.
  5. Repetitions of the same tool with the same arguments in a row - the model did not understand the result, it is corrected by the text of the tool’s response.

Separately check the limiters: insert a problem that is obviously unsolvable and make sure that the cycle stops at max_steps and writes the reason, and does not spin until the budget is exhausted. Then remove one tool from the allowlist and make sure that the attempted call ends in a code failure rather than execution.

  • ii-agents
  • architecture
  • tools
  • memory