Production Stack: Як зібрати надійну систему агентів

Production Stack поєднує Runtime, tools, memory, policy, HITL, containerization і multi-tenant межі в одну керовану систему.
На цій сторінці
  1. Ідея за 30 секунд
  2. Проблема
  3. Рішення
  4. Як працює Production Stack
  5. У коді це виглядає так
  6. Як це виглядає під час виконання
  7. Коли підходить — і коли ні
  8. Підходить
  9. Не підходить
  10. Типові проблеми та відмови
  11. Як поєднується з іншими патернами
  12. Коротко
  13. FAQ
  14. Що далі

Ідея за 30 секунд

Production Stack — це не один компонент, а узгоджений набір архітектурних шарів, які разом роблять агентну систему керованою в production.

Це не "більше промптів". Це явні межі відповідальності:

  • хто приймає рішення;
  • хто дозволяє або блокує дію;
  • де зберігається стан;
  • як контролюються ризики, бюджети і відмови.

Коли потрібно: коли агент має працювати довго, виконувати state-changing дії, обробляти багато клієнтів і залишатися передбачуваним під навантаженням.

LLM пропонує наступний крок, але Production Stack вирішує, чи можна цей крок виконати, де його виконати і як безпечно зупинити процес.


Проблема

Якщо будувати агент як "модель + кілька tool calls", система швидко стає крихкою.

Типові наслідки:

  • немає чітких stop conditions, тому агент застрягає в циклах;
  • немає policy-рамок, тому небезпечні дії проходять без контролю;
  • немає якісної пам'яті, тому з'являються дублікати, шум або помилкова персоналізація;
  • немає tenant-ізоляції, тому зростає ризик cross-tenant витоків;
  • немає операційної дисципліни, тому rollout, rollback і реагування на інциденти стають хаотичними;
  • немає наскрізного аудиту, тому після збою важко пояснити, що саме сталося.

У production це зазвичай означає інциденти безпеки, перевитрати бюджету і нестабільну якість відповідей.

Рішення

Додати Production Stack як явну архітектурну схему, де кожен шар має чіткий контракт і власну зону відповідальності.

Типовий склад стеку:

  1. Ingress + Auth (визначення actor/tenant);
  2. Orchestration Topology (route, handoff, stop);
  3. Agent Runtime (кроки, ліміти, reason_code);
  4. Tool Execution Layer (валідація і контроль side effects, тобто змін стану);
  5. Memory Layer (керований відбір/запис пам'яті);
  6. Policy Boundaries + Human-in-the-Loop (дозволити, заблокувати, погодити);
  7. Containerization + Observability + Operations (відтворюваний запуск, health checks, rollback);
  8. Multi-Tenant Isolation (ізоляція контексту, доступів і ресурсів).

Аналогія: як сучасний аеропорт.

Є реєстрація, контроль безпеки, маршрутизація, диспетчер, журнал подій і аварійні процедури.

Production Stack так само перетворює "один розумний модуль" на керовану систему з правилами виконання.

Як працює Production Stack

Production Stack з'єднує всі ключові межі в один керований цикл: від вхідного запиту до контрольованого виконання, аудиту і відновлення.

Diagram
Опис повного флоу: Identify → Plan → Decide → Gate → Execute → Learn → Observe → Recover

Identify
Ingress визначає actor, tenant, request_id і стартові ліміти.

Plan
Orchestration Topology вибирає маршрут задачі: один агент, кілька агентів або pipeline.

Decide
Agent Runtime формує наступний крок з урахуванням поточного стану і пам'яті.

Gate
Policy/HITL перевіряє ризик, allowlist, scopes, бюджет і вирішує: allow, require_approval, deny.

Execute
Tool Execution Layer валідовує аргументи, виконує дію і повертає нормалізований результат.

Learn
Memory Layer зберігає тільки корисні та безпечні факти з TTL, без накопичення шуму.

Observe
У трейс і аудит потрапляють рішення, reason_code, контекст і результат виконання або блокування.

Recover
Container/Ops-шар забезпечує health checks, rollback, kill switch і контрольований restart.

Цей цикл прибирає "магію" з агентної системи і робить її передбачуваною під реальним навантаженням.

У коді це виглядає так

PYTHON
class ProductionStack:
    def __init__(self, ingress, topology, runtime, memory, policy, hitl, tools, audit):
        self.ingress = ingress
        self.topology = topology
        self.runtime = runtime
        self.memory = memory
        self.policy = policy
        self.hitl = hitl
        self.tools = tools
        self.audit = audit

    def run(self, request, auth_token):
        ctx = self.ingress.identify(request=request, auth_token=auth_token)
        if not ctx.get("ok", False):
            return {"ok": False, "reason_code": ctx.get("reason_code", "auth_failed")}

        state = self.runtime.start(
            request=request,
            tenant_id=ctx["tenant_id"],
            budgets=ctx["budgets"],
        )

        while not self.runtime.should_stop(state):
            route = self.topology.next_step(state=state)
            route_mode = route.get("mode")

            if route_mode == "finish":
                return {
                    "ok": True,
                    "result": route.get("final_answer", ""),
                    "reason_code": "completed",
                }
            if route_mode != "action":
                return {"ok": False, "reason_code": "unknown_route_mode"}

            memory_items = self.memory.retrieve(
                tenant_id=ctx["tenant_id"],
                query=route["query"],
                top_k=4,
                min_score=0.7,
                exclude_expired=True,
            )

            action = self.runtime.decide(route=route, memory_items=memory_items)
            decision = self.policy.check(action=action, context=ctx)
            mode = decision.get("mode")

            if mode == "deny":
                self.audit.log(context=ctx, action=action, outcome="blocked", reason_code=decision.get("reason_code", "policy_denied"))
                return {"ok": False, "reason_code": decision.get("reason_code", "policy_denied")}
            elif mode == "require_approval":
                approval = self.hitl.review(action=action, context=ctx)
                if not approval.get("approved", False):
                    reason = approval.get("reason_code", "approval_rejected")
                    self.audit.log(context=ctx, action=action, outcome="blocked", reason_code=reason)
                    return {"ok": False, "reason_code": reason}
                action = approval.get("action_override", action)
            elif mode != "allow":
                reason = decision.get("reason_code", "policy_mode_invalid")
                self.audit.log(context=ctx, action=action, outcome="blocked", reason_code=reason)
                return {"ok": False, "reason_code": reason}

            result = self.tools.execute(action=action, context=ctx)
            self.audit.log(
                context=ctx,
                action=action,
                outcome="executed" if result.get("ok", False) else "failed",
                reason_code=result.get("reason_code", "tool_unknown"),
            )

            self.runtime.observe(state=state, action=action, result=result)
            self.memory.write_if_useful(
                tenant_id=ctx["tenant_id"],
                state=state,
                result=result,
            )

        return {"ok": False, "reason_code": self.runtime.stop_reason(state)}

Як це виглядає під час виконання

TEXT
Запит: "Підготуй комерційну пропозицію, узгодь ризикові пункти і надішли фінальну версію клієнту"

Step 1
Ingress + Auth: визначає actor, tenant, бюджети і request_id
Orchestration Topology: ділить задачу на етапи "збір", "проєкт", "фіналізація"

Step 2
Agent Runtime: формує action
Policy + HITL: для надсилання клієнту вмикає require_approval
Людина погоджує фінальну версію

Step 3
Tool Execution Layer: виконує погоджену дію
Memory Layer: зберігає важливі факти з TTL
Audit + Trace: фіксує decision, reason_code, outcome

Production Stack не замінює окремі патерни. Він з'єднує їх у керовану production-систему.

Коли підходить — і коли ні

Production Stack потрібен там, де агент має працювати як сервіс, а не як одноразовий демо-скрипт.

Підходить

СитуаціяЧому Production Stack підходить
Агент виконує state-changing дії у зовнішніх системахСтек додає policy/HITL-гейти, контроль side effects і аудит.
Сервіс працює з кількома клієнтами і різними правами доступуMulti-tenant межі, scoped credentials і пер-tenant ліміти зменшують ризик витоків.
Потрібна передбачуваність, SLO і зрозумілий postmortem після збоївЯвні stop reasons, трейс і операційні правила роблять відмови контрольованими.

Не підходить

СитуаціяЧому Production Stack не підходить
One-shot read-only демо з одним безпечним інструментомПовний стек додасть складність, яка не окупиться на цьому етапі.
Короткий внутрішній прототип без вимог до комплаєнсу, аудиту і SLAНа старті часто достатньо Runtime + базові ліміти, а решту шарів додавати поетапно.

Для мінімального прототипу інколи достатньо простого запуску:

PYTHON
result = runtime.run(task=request["text"], max_steps=8, max_seconds=20)

Типові проблеми та відмови

ПроблемаЩо відбуваєтьсяЯк запобігти
Нечіткі межі шарівЛогіка policy, memory і runtime змішується в одному місціЯвні контракти між шарами: хто приймає рішення, хто виконує, хто логує
Немає глобальних лімітівАгент витрачає зайві токени, кроки або бюджетЖорсткі ліміти на steps/time/cost і стандартизований stop_reason
Слабкий policy contextPolicy check приймає рішення без actor/tenant/scopesПередавати повний context: actor, tenant, resource, risk, budget
Погана якість пам'ятіАгент персоналізує відповідь на основі застарілих або слабких фактівПравила якості пам'яті: relevance, freshness, source, sensitivity, TTL
Слабка tenant-ізоляціяКеш, пам'ять або credentials змішуються між клієнтамиTenant-scoped namespace, ключі доступу і пер-tenant бюджети
Операційна нестабільністьПісля деплою змінюється поведінка через mutable image або непінені залежностіImmutable images, pinned dependencies, health checks, canary і швидкий rollback

Більшість production-проблем виникає не через одну "помилку моделі", а через слабкі межі між архітектурними шарами.

Як поєднується з іншими патернами

Production Stack не конкурує з іншими патернами. Він збирає їх в одну узгоджену систему.

  • Agent Runtime — керує циклом кроків і stop conditions.
  • Tool Execution Layer — контролює виконання інструментів і side effects (зміни стану).
  • Memory Layer — повертає і записує тільки корисну пам'ять за критеріями якості.
  • Policy Boundaries — визначає allow/deny/require_approval для ризикових дій.
  • Orchestration Topologies — задає маршрут задачі між агентами.
  • Hybrid Workflow Agent — розділяє deterministic workflow і bounded agent-рішення.
  • Human-in-the-Loop Architecture — додає контроль людини в критичних точках.
  • Containerizing Agents — дає відтворюване виконання, health checks і rollout-контроль.
  • Multi-Tenant — ізолює контекст, ресурси і доступи між клієнтами.

Інакше кажучи:

  • Production Stack визначає як усі ці шари працюють разом як одна система
  • Кожен окремий патерн закриває свій конкретний тип ризику

Коротко

Коротко

Production Stack:

  • перетворює агент із демо на керовану production-систему
  • розділяє відповідальність між Runtime, policy, tools, memory і ops
  • додає контроль ризику через бюджети, approval-гейти і аудит
  • робить поведінку агента передбачуваною під навантаженням

FAQ

Q: З чого почати, якщо немає ресурсу на весь стек одразу?
A: Почніть з Runtime (ліміти + stop reasons), Tool Execution Layer (валідація + timeout) і аудиту. Потім поетапно додавайте policy/HITL, якість пам'яті та multi-tenant ізоляцію.

Q: Чи можна мати Production Stack з одним агентом, без multi-agent топології?
A: Так. Топологія може бути простою, але інші шари все одно потрібні, якщо є ризикові дії або production-навантаження.

Q: Чи замінює Production Stack observability або SRE-практики?
A: Ні. Він включає їх як частину архітектури, але потребує операційної дисципліни: моніторинг, алерти, rollout і incident response.

Q: Що ламається першим, коли стек неповний?
A: Найчастіше ламаються межі виконання: або неконтрольовані tool calls, або шумна пам'ять, або policy-пропуски без аудиту.

Що далі

Production Stack — це карта всієї системи. Тепер можна заглибитись у шари, які найчастіше ламаються першими:

  • Tool Execution Layer — контроль інструментів, таймаутів і side effects (побічних ефектів, тобто змін стану).
  • Memory Layer — якість пам'яті, TTL і контроль чутливих даних.
  • Policy Boundaries — allow/deny/approval для ризикових дій.
  • Multi-Tenant — ізоляція контексту, ресурсів і бюджетів між клієнтами.
⏱️ 9 хв читанняОновлено 9 березня 2026 р.Складність: ★★★
Інтегровано: продакшен-контрольOnceOnly
Додай guardrails до агентів з tool-calling
Зашип цей патерн з governance:
  • Бюджетами (кроки / ліміти витрат)
  • Дозволами на інструменти (allowlist / blocklist)
  • Kill switch та аварійна зупинка
  • Ідемпотентність і dedupe
  • Audit logs та трасування
Інтегрована згадка: OnceOnly — контрольний шар для продакшен агент-систем.

Автор

Микола — інженер, який будує інфраструктуру для продакшн AI-агентів.

Фокус: патерни агентів, режими відмов, контроль рантайму та надійність систем.

🔗 GitHub: https://github.com/mykolademyanov


Редакційна примітка

Ця документація підготовлена з допомогою AI, із людською редакторською відповідальністю за точність, ясність і продакшн-релевантність.

Контент базується на реальних відмовах, постмортемах та операційних інцидентах у розгорнутих AI-агентних системах.