Multi-Tenant: Як ізолювати агентів між клієнтами

Керований архітектурний шар ізоляції tenant-даних: окремий контекст, scoped credentials, per-tenant ліміти і аудит без cross-tenant витоків.
На цій сторінці
  1. Ідея за 30 секунд
  2. Проблема
  3. Рішення
  4. Як працює Multi-Tenant
  5. У коді це виглядає так
  6. Як це виглядає під час виконання
  7. Коли підходить — і коли ні
  8. Підходить
  9. Не підходить
  10. Типові проблеми та відмови
  11. Як поєднується з іншими патернами
  12. Коротко
  13. FAQ
  14. Що далі

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

Multi-Tenant — це архітектурний підхід, у якому одна агентна система обслуговує багато клієнтів, але кожен tenant (окремий клієнт) ізольований.

Ізоляція має бути не лише в даних. Вона потрібна в усьому ланцюжку:

  • контекст Runtime;
  • пам'ять і кеш;
  • доступи до інструментів;
  • ліміти бюджету і rate limits;
  • аудит і трейс.

Коли потрібно: коли один сервіс працює для багатьох клієнтів, команд або workspace у спільній інфраструктурі.

LLM не має самостійно визначати tenant-контекст. Tenant має визначатися через auth або routing, а система примусово застосовує його на кожному кроці.


Проблема

Без чіткої multi-tenant ізоляції система працює, але ризики швидко стають критичними.

LLM-агенти збільшують ризик cross-tenant витоків, бо один запит може читати пам'ять, викликати інструменти і писати дані в кілька систем.

Типові збої:

  • контекст одного tenant потрапляє у відповідь іншому;
  • tool call виконується з чужими credentials;
  • пам'ять або кеш змішуються між клієнтами;
  • один tenant витрачає весь спільний бюджет (noisy neighbor);
  • аудит не дозволяє довести, хто саме ініціював дію.

У production це означає витоки даних, інциденти безпеки і складний комплаєнс.

Рішення

Додати Multi-Tenant як явну межу ізоляції (tenant boundary) між Agent Runtime і всіма станами/діями системи.

Ця межа визначає:

  • як ідентифікується tenant;
  • які ресурси доступні цьому tenant;
  • які ліміти застосовуються саме до нього;
  • як фіксується tenant-контекст у логах і трейсах.

Аналогія: як сейфові комірки в банку.

Будівля одна, але доступ до кожної комірки має тільки її власник.

Multi-Tenant так само дозволяє спільну платформу без змішування доступу і даних.

Як працює Multi-Tenant

Multi-Tenant — це керований шар між вхідним запитом і виконанням дій, який примусово ізолює кожен запуск за tenant_id.

Diagram
Опис повного флоу: Identify → Isolate → Authorize → Execute → Audit

Identify
Система визначає tenant через auth token, org mapping або routing-правила.

Isolate
Runtime, memory, cache і budget-контекст прив'язуються до конкретного tenant_id.

Authorize
Policy-шар перевіряє role, tenant scopes, allowlist і пер-tenant ліміти.

Execute
Виклики інструментів виконуються тільки з tenant-scoped credentials і ресурсами цього tenant.

Audit
Кожен критичний крок логується з tenant_id, actor_id, reason_code, outcome.

Цей цикл дозволяє масштабувати один сервіс на багато клієнтів без cross-tenant змішування.

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

PYTHON
class MultiTenantArchitecture:
    def __init__(self, auth, runtime, policy, tools, memory, budgets, audit):
        self.auth = auth
        self.runtime = runtime
        self.policy = policy
        self.tools = tools
        self.memory = memory
        self.budgets = budgets
        self.audit = audit

    def run(self, request, auth_token):
        identity = self.auth.resolve(auth_token) or {}
        tenant_id = identity.get("tenant_id")
        actor_id = identity.get("actor_id")
        if not tenant_id:
            return {"ok": False, "reason_code": "tenant_missing"}

        if not self.budgets.allowed(tenant_id=tenant_id):
            return {"ok": False, "reason_code": "tenant_budget_exceeded"}

        # Увесь контекст жорстко прив'язаний до tenant.
        state = self.runtime.start(request=request, tenant_id=tenant_id)
        memory_items = self.memory.retrieve(tenant_id=tenant_id, query=request["text"], top_k=4)
        action = self.runtime.decide(state=state, memory_items=memory_items)

        gate = self.policy.authorize(
            tenant_id=tenant_id,
            actor_id=actor_id,
            action=action,
        )
        if not gate["ok"]:
            self.audit.log(
                tenant_id=tenant_id,
                actor_id=actor_id,
                action=action.get("name"),
                outcome="denied",
                reason_code=gate.get("reason_code", "policy_denied"),
            )
            return {"ok": False, "reason_code": gate.get("reason_code", "policy_denied")}

        result = self.tools.execute(
            action=action,
            tenant_id=tenant_id,
            scopes=gate.get("scopes", []),
        )

        self.audit.log(
            tenant_id=tenant_id,
            actor_id=actor_id,
            action=action.get("name"),
            outcome="executed",
            reason_code=result.get("reason_code", "ok"),
        )
        return result

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

TEXT
Запит: "Онови статус замовлення #918 і надішли підтвердження клієнту"

Step 1
Auth + Routing: визначає tenant_id = tenant_acme
Multi-Tenant Boundary: встановлює tenant-контекст і пер-tenant ліміти

Step 2
Agent Runtime: формує action
Policy: перевіряє role + tenant scopes + allowlist
Tool Execution: виконує дію лише з credentials tenant_acme

Step 3
Audit: зберігає tenant_id, actor_id, action, outcome, reason_code
Runtime: повертає результат без змішування з іншими клієнтами

Multi-Tenant не змінює логіку агента. Він робить її передбачуваною і безпечною для багатоклієнтського середовища.

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

Multi-Tenant потрібен там, де одна система працює для багатьох клієнтів або команд із різними доступами.

Підходить

СитуаціяЧому Multi-Tenant підходить
Один агентний сервіс обслуговує багато клієнтівTenant boundary запобігає cross-tenant витокам даних і доступів.
Потрібні різні бюджети, квоти і policy rules для різних tenantПер-tenant ліміти захищають систему від noisy-neighbor ефекту.
Потрібен аудит для безпеки й комплаєнсуЛоги і трейс фіксують дії з чіткою прив'язкою до tenant.

Не підходить

СитуаціяЧому Multi-Tenant не підходить
Система обслуговує лише одного клієнта без планів масштабуванняПовна multi-tenant обв'язка може бути зайвою складністю на старті.
Дані та доступи вже фізично ізольовані окремими інсталяціямиУ такому випадку часто достатньо single-tenant архітектури на кожну інсталяцію.

У простому single-tenant сценарії інколи достатньо базового контексту:

PYTHON
result = runtime.run(request=request, tenant_id="default")

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

ПроблемаЩо відбуваєтьсяЯк запобігти
Credential bleedTool call використовує ключі іншого tenantTenant-scoped credentials + заборона глобальних клієнтів
Cache / memory bleedКеш або пам'ять повертають дані іншого tenantNamespace key із tenant_id, ізоляція store і тест-кейси на витоки
Noisy neighborОдин tenant забирає спільний бюджет і деградує сервіс для іншихPer-tenant budgets, rate limits, квоти і пріоритети
Підміна tenant-контекстуСистема приймає tenant_id з prompt або payload без перевірки authTenant визначається лише з auth/routing, а не з тексту запиту моделі
Неповний аудитНеможливо довести, який tenant ініціював ризикову діюОбов'язкові поля аудиту: tenant_id, actor_id, action, reason_code, outcome
Повторні write-операціїRetry дублює запис або списання в межах tenantIdempotency keys і дедуплікація для mutation-дій

Більшість multi-tenant інцидентів виникає не в моделі, а в слабкій межі між контекстом і виконанням.

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

Multi-Tenant — це поперечний архітектурний шар, який підсилює безпеку та стабільність усієї системи.

  • Agent Runtime — Runtime виконує кроки, а Multi-Tenant задає межі tenant-контексту на кожному кроці.
  • Tool Execution Layer — кожен tool_call має виконуватись із tenant-scoped доступами.
  • Memory Layer — пам'ять і кеш мають бути ізольовані за tenant_id.
  • Policy Boundaries — policy rules застосовуються з урахуванням tenant, role і scopes.
  • Orchestration Topologies — у multi-agent флоу tenant-контекст має передаватися між усіма гілками.
  • Hybrid Workflow Agent — workflow-коміти мають лишатися в межах ресурсів конкретного tenant.
  • Human-in-the-Loop Architecture — approval-кроки також повинні мати tenant-bound аудит і доступи.
  • Containerizing Agents — контейнери дають стабільне середовище, але tenant-ізоляцію забезпечує саме Multi-Tenant межа.

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

  • Multi-Tenant визначає чия це дія і чий це контекст
  • Інші архітектурні шари визначають як ця дія виконується

Коротко

Коротко

Multi-Tenant:

  • ізолює дані, доступи і state між клієнтами
  • застосовує пер-tenant ліміти бюджету і rate limits
  • примусово прив'язує tool calls до tenant-scoped credentials
  • робить аудит прозорим через tenant_id + reason_code

FAQ

Q: Чи достатньо просто додати tenant_id у запит?
A: Ні. tenant_id має примусово проходити через Runtime, policy, tools, memory, cache і audit.

Q: Де найчастіше стаються cross-tenant витоки?
A: Найчастіше в кешах, пам'яті і глобальних клієнтах для зовнішніх API.

Q: Як безпечно перейти з single-tenant на multi-tenant?
A: Почати з tenant_id в auth/routing, далі ізолювати memory/cache/tools, додати пер-tenant ліміти й аудит, і лише потім мігрувати дані поетапно.

Q: Що важливіше спочатку: пер-tenant бюджети чи пер-tenant policy?
A: Обидва важливі. Policy захищає доступи, бюджети захищають від noisy-neighbor і вибуху витрат.

Що далі

Multi-tenant архітектура починається з ізоляції, але не закінчується на ній. Далі подивіться, як утримати стабільність під реальним навантаженням:

  • Memory Layer — як будувати tenant-scoped пам'ять без витоків між клієнтами.
  • Containerizing Agents — як забезпечити відтворюване виконання для кожного tenant.
  • Policy Boundaries — як розвести доступи, ролі й ризикові дії.
  • Production Stack — як зібрати це в керовану production-модель.
⏱️ 8 хв читанняОновлено 8 березня 2026 р.Складність: ★★★
Інтегровано: продакшен-контрольOnceOnly
Додай guardrails до агентів з tool-calling
Зашип цей патерн з governance:
  • Бюджетами (кроки / ліміти витрат)
  • Дозволами на інструменти (allowlist / blocklist)
  • Kill switch та аварійна зупинка
  • Ідемпотентність і dedupe
  • Audit logs та трасування
Інтегрована згадка: OnceOnly — контрольний шар для продакшен агент-систем.

Автор

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

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

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


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

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

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