Запропонований контракт provisioning та оплати
AGNT2-532: Безкоштовно. Оплату поки не підключено. Для створення, активації та підключення організації не потрібні договір, договірний ліміт, картка або адреси повернення. Використання не створює заборгованості чи майбутніх платіжних зобов’язань. Технічні ліміти, затверджені політики, права операторів і явна активація платформою зберігаються. Майбутня оплата підключається окремо та явно; безкоштовний період не оплачується заднім числом.
Історичний проєкт
Ця сторінка фіксує попередній проєкт, а не поточний стан випуску. Підготовка ресурсів, scoped authorization і trusted MCP уже реалізовані в комітах Agentfy; див. контракт серверного чату та межі доказів. Браузерні/BONSITE протоколи й ширші пропозиції щодо оплати/життєвого циклу зберігають власні умови випуску. Бойовий запуск партнера не мається на увазі.
Атомарне створення та повтори
Параметр шляху {orgId} має збігатися з організацією, визначеною за перевіреним ключем; він не обирає іншу організацію й не надає до неї доступу. Див. затверджену угоду про іменування.
Спочатку перевіряється service credential: namespace/environment визначаються з нього, не з organizationId тіла. До виділення ресурсів перевіряються scope, subject/team mappings, profile entitlement, ліміти та billing consent. Одна транзакція БД записує external identity/actor (якщо нові), team, owner membership, payer assignment, durable operation та outbox. Наявний actor використовується лише у своєму namespace. Локальні записи відкочуються разом; зовнішні agent/provider calls — після commit.
Унікальність receipt: (namespace, operationKind, idempotencyKey), незалежно від rotated credential ID; кожна спроба аудіює фактичний ключ. Хешується canonical versioned request із нормалізованими defaults без transport headers. Той самий key/hash повертає ту саму operation, включно з pending/failed; інший hash — 409 idempotency_conflict. Рекомендоване зберігання receipt 30 днів, але permanent external-ID mapping та bootstrap fingerprint запобігають дублюванню після expiry. Втрачений response відновлюється retry/operation lookup.
Різні ключі для одного external team серіалізуються unique namespace/team ID. Однаковий fingerprint повертає вихідну operation; інший creator/profile/payer — 409 external_id_conflict. Повтор не відновлює removed creator membership, не змінює payer і не активує suspended/deleted team. Зміни — окремі авторизовані mutations із expected version. Відсутні/чужі references дають нерозкривний 404, без linked direct account details.
Outbox workers мають operation + step idempotency keys, claim leases і crash-safe retry. Agent allocation має stable team/external-agent uniqueness. Зберігаються pending, ready, failed, step, safe reason, retryability; ready лише після фактичного setup. Failed setup не залишає платної автоматики: dispatch потребує readiness, payer, budget. Provider setup має власний idempotency reference/reconciliation, не distributed transaction чи повторний charge.
Конкретні запропоновані запити
POST /v1/orgs/{orgId}/provisionings
Authorization: Bearer <provisioning-key>
Idempotency-Key: workspace-77-v1
Content-Type: application/json
{
"subject": { "externalUserId": "opaque-person-42" },
"team": { "externalId": "workspace-77", "name": "Workspace 77" },
"agent": {"externalId": "assistant", "profile": {"name": "Store assistant", "instructions": "Help the authorized user with the store.", "skill": {"name": "store-help", "description": "Store assistance", "body": "Use the attached MCP for authorized store requests."}}},
"payer": { "mode": "organization" }
}{
"success": true,
"data": {
"operationId": "operation-7",
"userId": "user-partner-42",
"teamId": "team-77",
"status": "pending",
"billingStatus": "active",
"version": 1
}
}Відповідь містить partner actor ID, ніколи linked direct ID/email/payment reference. Перше прийняття — 202; retry повертає ту саму operation, 202 поки pending, 200 у terminal state. GET /v1/orgs/{orgId}/operations/operation-7 повертає стан/stable IDs; failure — safe reason, retryable, correlation ID без secrets. Retryable failure продовжує ту саму operation; нерозв’язний conflict потребує окремого correction flow.
Team-paid: {"mode":"team","consentId":"consent-9"} або {"mode":"team"}. Single-use consent прив’язаний до namespace, external team ID, terms, independently authenticated direct payer, споживається атомарно. Без consent — billingStatus: "pending_acceptance", creator записаний як intended responsible actor, free entitlement збережений, paid work заборонена. Намір не є прийнятим особистим mandate. Effective assignment — team-paid/pending; пізніша згода активує його BillingAccount без нової команди чи ретроактивного боргу.
POST /v1/orgs/{orgId}/browser-authorizations
Authorization: Bearer <separate-identity-issuer-key>
Content-Type: application/json
{
"transactionId": "browser-transaction-8",
"externalUserId": "opaque-person-42",
"teamId": "team-77",
"nonce": "transaction-bound-nonce",
"purpose": "login"
}Додатково перевіряються backchannel proof і browser transaction. Результат — single-use callback code та вже зареєстрований redirect, не user access token. Довільний redirect або direct/global session заборонені. Redemption прив’язаний до браузера Agentfy, не загальний partner token endpoint.
| Запропонований endpoint | Потрібні повноваження/перевірки |
|---|---|
POST /v1/orgs/{orgId}/provisionings | provision:create; власний namespace, profile, безкоштовне використання в межах затвердженої політики ресурсів, без browser scope |
GET /v1/orgs/{orgId}/operations/:id | provision:read; власний namespace, safe response |
POST /v1/orgs/{orgId}/operations/:id/retry | provision:create; retryable step, та сама operation, current state/version |
POST /v1/orgs/{orgId}/browser-authorizations | Окремий identity:authorize; active bound transaction, subject, membership |
POST /v1/orgs/{orgId}/subjects/:id/suspend | identity:manage; власний subject, revoke contexts/agents |
POST /v1/teams/:id/invitations | Owner/admin membership, target/role policy, team version |
POST /invitations/:id/accept | Fresh exact-target proof, single-use, live inviter authority |
POST /account-links / DELETE /account-links/:id | Independent direct authentication; create також partner proof/confirmation/link lock |
POST /contexts | Direct proof + active link + policy/membership; без partner→direct elevation |
POST /v1/teams/:id/owner-transfers | Active owner, fresh proof, recipient/resulting role |
POST /owner-transfers/:id/accept | Intended active member, fresh proof, versioned team transaction |
POST /v1/teams/:id/payer-changes | Запит owner/delegated org billing; це не consent |
POST /payer-changes/:id/accept | Independent direct payer або org billing за свою org; provider readiness |
PATCH /billing-accounts/:id/contact | Billing authority, contact proof за потреби; без transfer liability |
Кожна mutation має CSRF-safe browser path або scoped server path, idempotency та expected-version checks при зміні стану. Unknown scopes denied. Provisioning key не викликає links/credentials/personal billing/platform admin. Browser не отримує server secrets.
Платити та володіти — різні дії
Оплата → Хто платить показує org, відповідального, contact, readiness, effective dates, pending proposal, historical debt, free/covered status. Змінити контакт змінює повідомлення, не liability/payment method. Передати оплату називає нового payer/cutoff: «Попередні рахунки залишаються попередньому платнику».
Новий payer обирає Перевірити й прийняти, входить незалежно, бачить team/org, currency, plan/usage terms, budget/date і дозволяє provider mandate. Membership необов’язкове; billing invitation не відкриває customer content. Старий payer зберігає invoice-only access після втрати membership. Default invite expiry 7 днів. Decline/expiry/cancel лишає старе assignment. Acceptance не дає ролей; partner key не приймає згоду за direct account, навіть owner.
Типовий switch — наступна межа billing period. Scheduled assignment створюється після provider readiness і перевірки terms; на activation consent/mandate перевіряються повторно. Lock team billing timeline + version; одна pending change, replacement явно скасовує стару. Stale/concurrent acceptance — 409 і новий review screen. В одній транзакції закрити [from, cutoff) і відкрити [cutoff, to) без gap/overlap. Якщо activation fails, старе assignment діє лише доки чинні старі mandate/agreement; інакше nonchargeable status та paid refusal. Не можна продовжувати припинену liability без згоди.
Лише майбутня платна модель, не поточне безкоштовне підключення: Покриває організація вимагає team/org policy, org financial authority, active agreement/budget. Preauthorized BONSITE provisioning agreement дає default consent у межах ліміту. Agentfy platform admin дозволяє internal sponsorship із reason/cost center: це cost, не revenue/collected cash, без рахунку собі. Removal coverage потребує replacement payer consent або stop paid work, не автоматичного списання з owner.
Org invoice містить лише externally payable org-paid assignments, із team/agent breakdown. Team-paid invoices окремі для кожної команди, навіть якщо один direct user платить за кілька. Приклад: org-paid A30 + B70 і team-paid C20 → рахунок BONSITE 100, C — 20; org usage report може показати 120, але це не борг BONSITE. Grouping/dedup key включає mode і teamId для team mode, разом із payer/currency/period/contract. Sponsorship не додає revenue. Не копіюємо payment method чи subscription іншому legal payer: новий mandate/subscription та coordinated old cancellation; provider incompatibility блокує перехід.
Usage, межі періодів і бюджети
Charge фіксує team/org/assignment/price version/currency/occurredAt. Late events належать за trusted server occurredAt та historical assignment, не delivery time/current payer. На cutoff розбити interval або settle bounded reservations з кожного боку; old authorization не фінансує new interval. Узгодити provider period/cutoff до activation. Old debt/refunds/invoices лишаються old payer; corrections — adjustment entries, не rewrite.
Dedup usage за stable event ID, callbacks за provider/event ID. Перевірити signature, durable intake перед ack, monotonic transitions, reconciliation reordered events із provider. Retry не дублює money/invoice. Integer pico-USD зберігається до invoice; rounding до currency minor units один раз із adjustment, без неузгодженого currency mixing. Usage total/sponsorship не доводить collected revenue.
Paid dispatch атомарно резервує hard budget наперед, консервативно для bounded work, потім reconciles actual. Бюджет payer використовує продажну суму у валюті акаунта: limit мінус settled charges та open reservations. Vendor costUsdPico safety cap — окрема внутрішня межа. Concurrent requests не витрачають останню одиницю двічі. Long work перевіряється bounded steps; release лише після definitive completion/safe reconciliation, не timeout, поки provider може списати. Немає payer/mandate/coverage/budget → Налаштуйте оплату / Ліміт досягнуто; наявні free plans діють у своїх реальних межах. Це майбутні гарантії, що потребують provider validation.
Передати профіль у запиті
Платформа один раз схвалює політику організації. Передавайте agent.profile у запиті створення: {name, instructions, skill: {name, description, body}, modelId?, mcp?: {url, requiredTools, trustedContext?}, worker?: {tools, egress?}}. Вміст у межах політики не потребує окремого схвалення. Без mcp агент лише розмовляє.
requiredTools — обов’язковий мінімум, а не перелік дозволених інструментів: доступні всі виявлені інструменти з урахуванням прав виклику та правил однакових імен. Кожен успішний PUT …/profile перечитує незмінене MCP-підключення після збереження профілю; зміну підключення й надалі обробляє worker налаштування. Зміна лише requiredTools також запускає перечитування, не зупиняючи працюючого агента.
Для всіх підключених MCP-серверів, зокрема доданих вручну, перший допустимий хід після MCP_TOOLS_REFRESH_SECONDS (типово 300 секунд) запускає фонове оновлення. Цей хід зберігає попередній список; нові інструменти доступні з наступного ходу після завершення оновлення. Неактивний агент не опитує сервер. Після помилки повтор відбувається через той самий інтервал; збереження профілю або кнопка оновлення не чекають завершення строку. Фонове виявлення обмежене 5 секундами на HTTP-обмін і не затримує хід, який його запустив.
Метадані з переданим секретом і список без обов’язкового інструмента відхиляються. Останній успішний список і час його виявлення зберігаються; lastError видно в налаштуваннях MCP агента, і він очищується після успішного оновлення. Клієнт не тримає з’єднання між запитами та не підписується на notifications/tools/list_changed; оновлення забезпечують збереження профілю та перевірка строку.
Модель має входити до allowedModels, хост MCP — проходити перевірку публічної адреси та входити до mcpHosts, якщо увімкнено mcpHostsRestricted. Довірений контекст потребує trustedContextAllowed; інструменти й мережа воркера обмежені workerTools і workerEgress, а також межею розгортання. Ліміти символів: ім’я 120, інструкції 16 000, ім’я skill 64, опис 1 024, тіло 32 000. MCP-інструменти: 1–64, worker-інструменти: 1–16, мережеві адреси: до 64.
Порушення політики повертає HTTP 422 до створення ресурсів: code: policy_violation, message: policy_violation: <field>. Поля: policy, modelId, mcpHosts, mcp.url, trustedContextAllowed, workerTools, workerEgress. Виправте профіль або отримайте схвалення зміни політики та надішліть запит знову. Каталог моделей і план команди перевіряються під час підготовки.
Той самий agent.profile приймає ручка додаткового агента; у ній немає team і payer. Без MCP не потрібні конфігурація та виявлення інструментів. З MCP передайте ключ нижче й дочекайтеся виявлення.
Прийнятий вміст заморожується у знімку операції та fingerprint запиту. Повтор зберігає знімок, навіть якщо політика змінилася. Інший вміст із тим самим ключем дає IDEMPOTENCY_CONFLICT, із тією самою живою зовнішньою резервацією — EXTERNAL_ID_CONFLICT. Зміна вмісту живого агента належить до окремого процесу оновлення на місці, а не до зняття з обліку. Зняття призначене для навмисного видалення чи заміни.
agent.profile обов’язковий. Якщо modelId відсутній, використовується перша модель схваленої політики. Видалені поля templateId та templateVersion, як і інші невідомі поля, повертають 422. Каталогу збереженого вмісту й типового вибору немає.
На вкладці «Політика» прапорець Усі інструменти зберігає workerTools: ["*"]: політика допускає всі поточні та майбутні інструменти воркера. Список окремих інструментів при цьому вимкнено. Агент далі запитує конкретні інструменти; мережеві адреси та межі розгортання перевіряються окремо.
Адмінка → Організації → Створені агенти показує всі прийняті редакції профілю, час та ID ключа відправника. PUT /v1/orgs/{orgId}/operations/{operationId}/profile приймає { expectedVersion, profile } з ключем provisioning. Повний профіль ready-операції замінюється з перевіркою поточної політики; ID агента, бесіди та початковий fingerprint POST зберігаються. Застаріла версія повертає 409 OPERATION_VERSION_CONFLICT. Зміни підключення потребують повторної перевірки в pending; лише вміст змінюється без виходу з ready. Див. крок 8 посібника.
Крок 1 — схвалити політику організації
У застосунку відкрийте Організації → потрібна організація → Політика. Власник або адміністратор задає моделі, хости MCP, довірений контекст, інструменти та адреси воркера, максимум команд, зберігає чернетку й надсилає на схвалення. Адміністратор платформи відкриває чергу політик у розділі організацій адмінки, перевіряє зміни та схвалює або відхиляє з причиною. Лише схвалена політика дозволяє підготовку; попередня версія діє до схвалення нової.
Помилка policy_violation: <field> вказує дозвіл, який треба виправити. Розширте політику, отримайте схвалення та повторіть операцію з її поточною версією. Адреси воркера мають також входити до RUNTIME_WORKER_EGRESS_ALLOWLIST; перевірка публічних адрес зберігається.
Обмеження MCP-доменів необов’язкове: редактор нової політики надсилає mcpHostsRestricted: false, тому публічний MCP URL у профілі агента не потребує окремого домену в політиці. У додаткових налаштуваннях увімкніть «Дозволяти лише вказані MCP-домени», щоб перевіряти mcpHosts; увімкнене обмеження з порожнім списком забороняє всі MCP-підключення. Наявні політики та старі API-запити без прапорця зберігають обмеження, зокрема порожні списки. Режим застосовується після надсилання/схвалення політики. Решта вимог схвалення, перевірка URL, захист приватних адрес і мережеві обмеження платформи та воркера залишаються.